void Bot::Kill (void) { // this function kills a bot (not just using ClientKill, but like the CSBot does) // base code courtesy of Lazy (from bots-united forums!) edict_t *hurtEntity = (*g_engfuncs.pfnCreateNamedEntity) (MAKE_STRING ("trigger_hurt")); if (FNullEnt (hurtEntity)) return; hurtEntity->v.classname = MAKE_STRING (g_weaponDefs[m_currentWeapon].className); hurtEntity->v.dmg_inflictor = GetEntity (); hurtEntity->v.dmg = 9999.0f; hurtEntity->v.dmg_take = 1.0f; hurtEntity->v.dmgtime = 2.0f; hurtEntity->v.effects |= EF_NODRAW; (*g_engfuncs.pfnSetOrigin) (hurtEntity, Vector (-4000, -4000, -4000)); KeyValueData kv; kv.szClassName = const_cast <char *> (g_weaponDefs[m_currentWeapon].className); kv.szKeyName = "damagetype"; kv.szValue = FormatBuffer ("%d", (1 << 4)); kv.fHandled = false; MDLL_KeyValue (hurtEntity, &kv); MDLL_Spawn (hurtEntity); MDLL_Touch (hurtEntity, GetEntity ()); (*g_engfuncs.pfnRemoveEntity) (hurtEntity); }
CBaseEntity *GiveNamedItemInternal(AMX *amx, CBasePlayer *pPlayer, const char *pszItemName, const size_t uid) { edict_t *pEdict = CREATE_NAMED_ENTITY(ALLOC_STRING(pszItemName)); if (FNullEnt(pEdict)) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: Item \"%s\" failed to create!\n", __FUNCTION__, pszItemName); return nullptr; } pEdict->v.origin = pPlayer->pev->origin; pEdict->v.spawnflags |= SF_NORESPAWN; // In some cases, we must to sets unique id // for the entity before it will triggered a spawn. pEdict->v.impulse = uid; MDLL_Spawn(pEdict); MDLL_Touch(pEdict, ENT(pPlayer->pev)); CBaseEntity *pEntity = getPrivate<CBaseEntity>(pEdict); // not allow the item to fall to the ground. if (FNullEnt(pEntity->pev->owner) || pEntity->pev->owner != pPlayer->edict()) { pEntity->pev->targetname = iStringNull; pEntity->pev->flags |= FL_KILLME; return nullptr; } return pEntity; }
//shamelessly pulled from fun static cell AMX_NATIVE_CALL csdm_give_item(AMX *amx, cell *params) // native give_item(index, const item[]); = 2 params { // Check index. if (params[1] < 1 || params[1] > gpGlobals->maxClients) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid player %d", params[1]); return 0; } else if (!MF_IsPlayerIngame(params[1])) { MF_LogError(amx, AMX_ERR_NATIVE, "Player %d is not in game", params[1]); return 0; } // Get player pointer. edict_t *pPlayer = MF_GetPlayerEdict(params[1]); // Create item entity pointer edict_t *pItemEntity; // Make an "intstring" out of 2nd parameter int length; const char *szItem = MF_GetAmxString(amx, params[2], 1, &length); //check for valid item if (strncmp(szItem, "weapon_", 7) && strncmp(szItem, "ammo_", 5) && strncmp(szItem, "item_", 5) && strncmp(szItem, "tf_weapon_", 10) ) { return 0; } string_t item = ALLOC_STRING(szItem); // Using MAKE_STRING makes "item" contents get lost when we leave this scope! ALLOC_STRING seems to allocate properly... pItemEntity = CREATE_NAMED_ENTITY(item); if (FNullEnt(pItemEntity)) { MF_LogError(amx, AMX_ERR_NATIVE, "Item \"%s\" failed to create", szItem); return 0; } pItemEntity->v.origin = pPlayer->v.origin; pItemEntity->v.spawnflags |= (1 << 30); //SF_NORESPAWN; MDLL_Spawn(pItemEntity); int save = pItemEntity->v.solid; MDLL_Touch(pItemEntity, ENT(pPlayer)); if (pItemEntity->v.solid == save) { REMOVE_ENTITY(pItemEntity); //the function did not fail - we're just deleting the item return -1; } return ENTINDEX(pItemEntity); }
static cell AMX_NATIVE_CALL fake_touch(AMX *amx, cell *params) { int iPtr = params[1]; int iPtd = params[2]; CHECK_ENTITY(iPtr); CHECK_ENTITY(iPtd); edict_t *pToucher = INDEXENT2(iPtr); edict_t *pTouched = INDEXENT2(iPtd); MDLL_Touch(pToucher, pTouched); return 1; }
static cell AMX_NATIVE_CALL give_item(AMX *amx, cell *params) // native give_item(index, const item[]); = 2 params { /* Gives item to player, name of item can start * with weapon_, ammo_ and item_. This event * is announced with proper message to all players. */ // params[1] = index // params[2] = item... // Check index. CHECK_PLAYER(params[1]); // Get player pointer. edict_t *pPlayer = MF_GetPlayerEdict(params[1]); // Create item entity pointer edict_t *pItemEntity; // Make an "intstring" out of 2nd parameter int length; const char *szItem = MF_GetAmxString(amx, params[2], 1, &length); //check for valid item if (strncmp(szItem, "weapon_", 7) && strncmp(szItem, "ammo_", 5) && strncmp(szItem, "item_", 5) && strncmp(szItem, "tf_weapon_", 10) ) { return 0; } //string_t item = MAKE_STRING(szItem); string_t item = ALLOC_STRING(szItem); // Using MAKE_STRING makes "item" contents get lost when we leave this scope! ALLOC_STRING seems to allocate properly... // Create the entity, returns to pointer pItemEntity = CREATE_NAMED_ENTITY(item); if (FNullEnt(pItemEntity)) { MF_LogError(amx, AMX_ERR_NATIVE, "Item \"%s\" failed to create", szItem); return 0; } //VARS(pItemEntity)->origin = VARS(pPlayer)->origin; // nice to do VARS(ent)->origin instead of ent->v.origin? :-I //I'm not sure, normally I use macros too =P pItemEntity->v.origin = pPlayer->v.origin; pItemEntity->v.spawnflags |= SF_NORESPAWN; //SF_NORESPAWN; MDLL_Spawn(pItemEntity); int save = pItemEntity->v.solid; MDLL_Touch(pItemEntity, ENT(pPlayer)); //The problem with the original give_item was the // item was not removed. I had tried this but it // did not work. OLO's implementation is better. /* int iEnt = ENTINDEX(pItemEntity->v.owner); if (iEnt > 32 || iEnt <1 ) { MDLL_Think(pItemEntity); }*/ if (pItemEntity->v.solid == save) { REMOVE_ENTITY(pItemEntity); //the function did not fail - we're just deleting the item return -1; } return ENTINDEX(pItemEntity); }