[SNIPPET] NPC DeathMSG

For scripting examples for learning how to use AMXX.
User avatar
Archive-Poster
Posts: 1229
Gender:
United States of America

[SNIPPET] NPC DeathMSG

Post by Archive-Poster »

I've found a way to make an npc fake deathmsg, i thought i'd share since i had never found something similar on the web.

Code: Select all

#include <fakemeta>

#define TASK_NPC_DEATHMSG 11030

enum any:DEATHMSG_DATA (+=1) {
    DEATHMSG_VICTIM_ID = 0,
    DEATHMSG_KILLER_ID,
    bool:DEATHMSG_bHEADSHOT,
    DEATHMSG_WEAPON_NAME[24],
    DEATHMSG_VIC_NAME[32],
    DEATHMSG_KILLER_NAME[32]
}

public NPC_ENTITY_KILLED_PRE(const id, const killer, const gibs)
{
    static szClass[32];
    pev(id, pev_classname, szClass, charsmax(szClass));

    set_pev(id, pev_deadflag, DEAD_DYING);
    set_pev(id, pev_takedamage, DAMAGE_NO);
    set_pev(id, pev_solid, SOLID_NOT);

    set_pev(id, PEV_TASK, NPC_DEATH);

    static szVicName[32];
    pev(id, pev_netname, szVicName, charsmax(szVicName));
    pev(id, PEV_WEAPON_INFLICTOR, szClass, charsmax(szClass));

    if(!szVicName[0])
    {
        copy(szVicName, charsmax(szVicName), "Unnamed");
        set_pev(id, pev_netname, szVicName);
    }

    new iPlayerPointer = get_user_index(szVicName);

    if( iPlayerPointer )
    {
        remove_task( iPlayerPointer + TASK_NPC_DEATHMSG );
    }

    static iNPC_DeathMSG_Data[DEATHMSG_DATA];
    iNPC_DeathMSG_Data[DEATHMSG_VICTIM_ID] = id;
    iNPC_DeathMSG_Data[DEATHMSG_KILLER_ID] = killer;

    iNPC_DeathMSG_Data[DEATHMSG_KILLER_NAME][0] = EOS;

    if(IsPlayer(killer))
    {
        get_user_name(killer, iNPC_DeathMSG_Data[DEATHMSG_KILLER_NAME], charsmax(iNPC_DeathMSG_Data[DEATHMSG_KILLER_NAME]));
    }
    else if(killer && (pev(killer, pev_flags) & FL_MONSTER))
    {
        static szKillerName[32];
        pev(killer, pev_netname, szKillerName, charsmax(szKillerName));

        if(!szKillerName[0])
        {
            copy(szKillerName, charsmax(szKillerName), "Unnamed");
            set_pev(killer, pev_netname, szKillerName);
        }

        copy(iNPC_DeathMSG_Data[DEATHMSG_KILLER_NAME], charsmax(iNPC_DeathMSG_Data[DEATHMSG_KILLER_NAME]), szKillerName);

        iPlayerPointer = get_user_index(szKillerName);

        if( iPlayerPointer )
        {
            remove_task( iPlayerPointer + TASK_NPC_DEATHMSG );
        }
    }

    iNPC_DeathMSG_Data[DEATHMSG_bHEADSHOT] = false;
    copy(iNPC_DeathMSG_Data[DEATHMSG_WEAPON_NAME], charsmax(iNPC_DeathMSG_Data[DEATHMSG_WEAPON_NAME]), szClass);
    copy(iNPC_DeathMSG_Data[DEATHMSG_VIC_NAME], charsmax(iNPC_DeathMSG_Data[DEATHMSG_VIC_NAME]), szVicName);

    static xFuncID, iReturnVal;
    pev(id, pev_classname, szClass, charsmax(szClass));
    TrieGetCell(g_trie_NPC_CLASS_DEATH_CALLBACK, szClass, xFuncID);
    if( xFuncID != INVALID_HANDLE )
    {
        ExecuteForward(xFuncID, iReturnVal, id, killer, gibs);
    }

    Initiate_NPC_DEATHMSG(iNPC_DeathMSG_Data);

    // Lets call think
    set_pev(id, pev_nextthink, get_gametime() + NPC_THINK_LEN);
    call_think(id);

    return HAM_SUPERCEDE;
}

stock Initiate_NPC_DEATHMSG(const iNPC_DeathMSG_Data[DEATHMSG_DATA])
{
    static szParam[16], Array:xArray;
    ArrayPushArray((xArray = ArrayCreate(DEATHMSG_DATA, 1)), iNPC_DeathMSG_Data);
    num_to_str(_:xArray, szParam, charsmax(szParam));

    static const Float:fInterval_len = 1.0;
    static Float:finterval = 0.0, Float:fGameTime;
    fGameTime = get_gametime();

    if(finterval >= fGameTime)
        finterval += fInterval_len;
    else
        finterval = fGameTime + fInterval_len;

    set_task((finterval - fGameTime), "task_interval_NPC_DEATHMSG", iNPC_DeathMSG_Data[DEATHMSG_VICTIM_ID] + TASK_NPC_DEATHMSG, szParam, sizeof szParam);
}

public task_interval_NPC_DEATHMSG(const param[], taskid)
{
    static Array:xArray, iNPC_DeathMSG_Data[DEATHMSG_DATA];
    xArray = any:str_to_num(param);
    ArrayGetArray(xArray, 0, iNPC_DeathMSG_Data);
    ArrayDestroy(xArray);
    Make_NPC_DeathMsg(iNPC_DeathMSG_Data[DEATHMSG_VICTIM_ID], iNPC_DeathMSG_Data[DEATHMSG_KILLER_ID],
        iNPC_DeathMSG_Data[DEATHMSG_VIC_NAME], iNPC_DeathMSG_Data[DEATHMSG_KILLER_NAME],
        iNPC_DeathMSG_Data[DEATHMSG_bHEADSHOT], iNPC_DeathMSG_Data[DEATHMSG_WEAPON_NAME]);
}

stock Make_NPC_DeathMsg(id, killer, const vicName[32], const killerName[32], const bool:bHeadshot, const weapon[24])
{
    if(!id || vicName[0] == EOS)
    {
        log_error(AMX_ERR_NATIVE, "Attempting to create an NPC DeathMSG with invalid id or vicName!");
        return;
    }

    static iMsg_TeamInfo = 0;
    if(!iMsg_TeamInfo) iMsg_TeamInfo = get_user_msgid("TeamInfo");

    enum (+=1) {
        VICTIM_ID = 0,
        KILLER_ID
    }

    new iTargets[2];
    iTargets[VICTIM_ID] = id;
    iTargets[KILLER_ID] = killer;

    static szRejectReason[128], szName[2][32];

    copy(szName[VICTIM_ID], charsmax(szName[]), vicName);
    copy(szName[KILLER_ID], charsmax(szName[]), killerName);

    if(killerName[0] == EOS)
    {
        copy(szName[KILLER_ID], charsmax(szName[]), "World");
    }

    for(new i, iTarget; i < 2; i++)
    {
        if(szName[i][0] == EOS) continue;

        iTarget = iTargets[i];

        if(get_user_index(szName[i]) != iTarget)
        {
            iTarget = iTargets[i] = get_user_index(szName[i]);
        }

        if( iTarget > 0 )
        {
            if( IsPlayer(iTarget) && (is_user_connected(iTarget) || is_user_connecting(iTarget)) )
            {
                remove_task( iTarget + TASK_NPC_DEATHMSG );
                continue;
            }
        }

        if( (KILLER_ID == i && iTargets[i] == iTargets[VICTIM_ID]) )
        {
            continue;
        }

        iTargets[i] = iTarget = engfunc(EngFunc_CreateFakeClient, szName[i]);

        if(!iTarget)
            continue;

        engfunc(EngFunc_FreeEntPrivateData, iTarget);
        if(dllfunc(DLLFunc_ClientConnect, iTarget , szName[i], "127.0.0.1", szRejectReason))
        {
            dllfunc(DLLFunc_ClientPutInServer, iTarget);
            set_pev(iTarget, pev_flags, pev(iTarget, pev_flags) | FL_FAKECLIENT);
            set_pev(iTarget, pev_deadflag, DEAD_DISCARDBODY);

            message_begin(MSG_BROADCAST, iMsg_TeamInfo, {0,0,0}, 0);
            write_byte(iTarget);
            write_string("TERRORIST");
            message_end();

            set_rendering(iTarget, kRenderFxNone, 0, 0, 0, kRenderTransAlpha);
        }
    }

    new szParam[16], Array:xArray, iNPC_DeathMSG_Data[DEATHMSG_DATA];
    iNPC_DeathMSG_Data[DEATHMSG_VICTIM_ID] = get_user_userid(iTargets[VICTIM_ID]);
    iNPC_DeathMSG_Data[DEATHMSG_KILLER_ID] = get_user_userid(iTargets[KILLER_ID]);
    iNPC_DeathMSG_Data[DEATHMSG_bHEADSHOT] = _:bHeadshot;
    copy(iNPC_DeathMSG_Data[DEATHMSG_WEAPON_NAME], charsmax(iNPC_DeathMSG_Data[DEATHMSG_WEAPON_NAME]), weapon);
    copy(iNPC_DeathMSG_Data[DEATHMSG_KILLER_NAME], charsmax(iNPC_DeathMSG_Data[DEATHMSG_KILLER_NAME]), killerName);
    copy(iNPC_DeathMSG_Data[DEATHMSG_VIC_NAME], charsmax(iNPC_DeathMSG_Data[DEATHMSG_VIC_NAME]), vicName);
    ArrayPushArray((xArray = ArrayCreate(DEATHMSG_DATA,1)), iNPC_DeathMSG_Data);
    num_to_str(_:xArray, szParam, charsmax(szParam));
    set_task(0.5, "declare_npc_deathmsg", id + TASK_NPC_DEATHMSG, szParam, sizeof szParam);
}

public declare_npc_deathmsg(const szParam[16], const taskid)
{
    new Array:xArray = any:str_to_num(szParam), iNPC_DeathMSG_Data[DEATHMSG_DATA];
    ArrayGetArray(xArray, 0, iNPC_DeathMSG_Data);

    new victim = find_player("k", iNPC_DeathMSG_Data[DEATHMSG_VICTIM_ID]),
    killer = find_player("k", iNPC_DeathMSG_Data[DEATHMSG_KILLER_ID]);

    if( !is_user_connected(victim) && !is_user_connecting(victim) ||
        !is_user_connected(killer) && !is_user_connecting(killer)  )
    {
        ArrayDestroy(xArray);

        remove_task(victim + TASK_NPC_DEATHMSG);
        remove_task(killer + TASK_NPC_DEATHMSG);

        iNPC_DeathMSG_Data[DEATHMSG_VICTIM_ID] = victim;
        iNPC_DeathMSG_Data[DEATHMSG_KILLER_ID] = killer;
        Initiate_NPC_DEATHMSG(iNPC_DeathMSG_Data);
        return;
    }

    new szNetName[2];
    pev(victim, pev_netname, szNetName, 1);
    if(szNetName[0] == EOS)
    {
        set_task(0.1, "declare_npc_deathmsg", taskid, szParam, sizeof szParam);
        return;
    }

    ArrayDestroy(xArray);

    make_deathmsg(killer, victim,  iNPC_DeathMSG_Data[DEATHMSG_bHEADSHOT], iNPC_DeathMSG_Data[DEATHMSG_WEAPON_NAME]);

    if(killer > 0 && pev(killer, pev_flags) & FL_FAKECLIENT)
    {
        remove_task(killer + TASK_NPC_DEATHMSG);
        set_task(1.0, "task_kick_bot", killer + TASK_NPC_DEATHMSG);
    }

    if(victim > 0 && pev(victim, pev_flags) & FL_FAKECLIENT)
    {
        remove_task(victim + TASK_NPC_DEATHMSG);
        set_task(1.0, "task_kick_bot", victim + TASK_NPC_DEATHMSG);
    }
}

public task_kick_bot(id)
{
    id -= TASK_NPC_DEATHMSG;

    if(is_user_bot(id))
    {
        server_cmd("kick #%d;", get_user_userid(id));
    }
} 
basically what this function do is it creates a bot if an npc entity id was passed into either the killer or id ( victim ) parameters or both, and it kicks the bot/s once the fake deathmsg is sent.

NPC entity name must be set into globalname keyvalue, or you can change that if you're using one npc name for all.

Adding a delay of 1.0 second to Make_NPC_DeathMsg is recommended if you're going to call it many times per second.

Who is online

Users browsing this forum: No registered users and 0 guests