Merge of rewritten NS module into trunk
This commit is contained in:
553
dlls/ns/natives/general.cpp
Normal file
553
dlls/ns/natives/general.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
/* AMX Mod X
|
||||
* Natural Selection Module
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
*
|
||||
* This file is part of AMX Mod X.
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../sdk/amxxmodule.h"
|
||||
|
||||
#include "cbase.h" // TakeDamage
|
||||
|
||||
#include "../ns.h"
|
||||
|
||||
#include "../utilfunctions.h"
|
||||
#include "../NEW_Util.h"
|
||||
|
||||
#include "../GameManager.h"
|
||||
#include "../SpawnManager.h"
|
||||
#include "../LocationManager.h"
|
||||
#include "../TitleManager.h"
|
||||
|
||||
#include "../CPlayer.h"
|
||||
|
||||
|
||||
edict_t* avhgameplay=NULL;
|
||||
|
||||
// drop-in replacement for user_kill
|
||||
static cell AMX_NATIVE_CALL ns_user_kill(AMX *amx, cell *params)
|
||||
{
|
||||
|
||||
CreatePlayerPointer(amx,params[1]);
|
||||
|
||||
// 2 is commander, never slay commander
|
||||
if (player->GetPev()->iuser3 == 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (MF_IsPlayerIngame(params[1]) && MF_IsPlayerAlive(params[1]))
|
||||
{
|
||||
REAL bef = player->GetPev()->frags;
|
||||
|
||||
edict_t *pEntity = CREATE_NAMED_ENTITY(MAKE_STRING("trigger_hurt"));
|
||||
|
||||
if (pEntity)
|
||||
{
|
||||
KeyValueData kvd;
|
||||
|
||||
kvd.szClassName="trigger_hurt";
|
||||
kvd.szKeyName="classname";
|
||||
kvd.szValue="trigger_hurt";
|
||||
kvd.fHandled=0;
|
||||
MDLL_KeyValue(pEntity,&kvd);
|
||||
|
||||
kvd.szClassName="trigger_hurt";
|
||||
kvd.szKeyName="dmg";
|
||||
kvd.szValue="50000.0";
|
||||
kvd.fHandled=0;
|
||||
MDLL_KeyValue(pEntity,&kvd);
|
||||
|
||||
kvd.szClassName="trigger_hurt";
|
||||
kvd.szKeyName="damagetype";
|
||||
kvd.szValue="1";
|
||||
kvd.fHandled=0;
|
||||
MDLL_KeyValue(pEntity,&kvd);
|
||||
|
||||
kvd.szClassName="trigger_hurt";
|
||||
kvd.szKeyName="origin";
|
||||
kvd.szValue="8192 8192 8192";
|
||||
kvd.fHandled=0;
|
||||
MDLL_KeyValue(pEntity,&kvd);
|
||||
|
||||
MDLL_Spawn(pEntity);
|
||||
|
||||
pEntity->v.classname=MAKE_STRING("slay");
|
||||
|
||||
MDLL_Touch(pEntity,player->GetEdict());
|
||||
|
||||
REMOVE_ENTITY(pEntity);
|
||||
}
|
||||
|
||||
// If the optional parameter is 1, restore the frag count
|
||||
if (params[2])
|
||||
{
|
||||
player->GetPev()->frags = bef;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
// drop-in replacement for user_slap
|
||||
#define ANGLEVECTORS (*g_engfuncs.pfnAngleVectors)
|
||||
static cell AMX_NATIVE_CALL ns_user_slap(AMX *amx, cell *params) /* 2 param */
|
||||
{
|
||||
|
||||
CreatePlayerPointer(amx,params[1]);
|
||||
|
||||
int power = abs((int)params[2]);
|
||||
|
||||
// Check if commander, if player is comm then stop
|
||||
if (player->GetPev()->iuser3 == 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (MF_IsPlayerIngame(player->index()) && MF_IsPlayerAlive(player->index()))
|
||||
{
|
||||
if (player->GetPev()->health <= power)
|
||||
{
|
||||
float bef = player->GetPev()->frags;
|
||||
/*MDLL_ClientKill(pPlayer->pEdict);*/
|
||||
edict_t *pEntity = CREATE_NAMED_ENTITY(MAKE_STRING("trigger_hurt"));
|
||||
if (pEntity)
|
||||
{
|
||||
KeyValueData kvd;
|
||||
|
||||
kvd.szClassName="trigger_hurt";
|
||||
kvd.szKeyName="classname";
|
||||
kvd.szValue="trigger_hurt";
|
||||
kvd.fHandled=0;
|
||||
MDLL_KeyValue(pEntity,&kvd);
|
||||
|
||||
kvd.szClassName="trigger_hurt";
|
||||
kvd.szKeyName="dmg";
|
||||
kvd.szValue="20000.0";
|
||||
kvd.fHandled=0;
|
||||
MDLL_KeyValue(pEntity,&kvd);
|
||||
|
||||
kvd.szClassName="trigger_hurt";
|
||||
kvd.szKeyName="damagetype";
|
||||
kvd.szValue="1";
|
||||
kvd.fHandled=0;
|
||||
MDLL_KeyValue(pEntity,&kvd);
|
||||
|
||||
kvd.szClassName="trigger_hurt";
|
||||
kvd.szKeyName="origin";
|
||||
kvd.szValue="8192 8192 8192";
|
||||
kvd.fHandled=0;
|
||||
MDLL_KeyValue(pEntity,&kvd);
|
||||
|
||||
MDLL_Spawn(pEntity);
|
||||
|
||||
pEntity->v.classname=MAKE_STRING("slap");
|
||||
|
||||
MDLL_Touch(pEntity,player->GetEdict());
|
||||
|
||||
REMOVE_ENTITY(pEntity);
|
||||
}
|
||||
|
||||
player->GetPev()->frags = bef;
|
||||
}
|
||||
else
|
||||
{
|
||||
int numparam = *params/sizeof(cell);
|
||||
if (numparam<3 || params[3])
|
||||
{
|
||||
player->GetPev()->velocity.x += RANDOM_LONG(-600,600);
|
||||
player->GetPev()->velocity.y += RANDOM_LONG(-180,180);
|
||||
player->GetPev()->velocity.z += RANDOM_LONG(100,200);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3_t v_forward, v_right;
|
||||
vec3_t vang = player->GetPev()->angles;
|
||||
float fang[3];
|
||||
fang[0] = vang.x;
|
||||
fang[1] = vang.y;
|
||||
fang[2] = vang.z;
|
||||
ANGLEVECTORS( fang, v_forward, v_right, NULL );
|
||||
player->GetPev()->velocity = player->GetPev()->velocity + v_forward * 220 + Vector(0,0,200);
|
||||
}
|
||||
player->GetPev()->punchangle.x = RANDOM_LONG(-10,10);
|
||||
player->GetPev()->punchangle.y = RANDOM_LONG(-10,10);
|
||||
|
||||
player->GetPev()->health -= power;
|
||||
|
||||
int armor = (int)player->GetPev()->armorvalue;
|
||||
armor -= power;
|
||||
|
||||
if (armor < 0)
|
||||
{
|
||||
armor = 0;
|
||||
}
|
||||
|
||||
player->GetPev()->armorvalue = armor;
|
||||
|
||||
player->GetPev()->dmg_inflictor = player->GetEdict();
|
||||
|
||||
static const char *bit_sound[3] = {
|
||||
"weapons/cbar_hitbod1.wav",
|
||||
"weapons/cbar_hitbod2.wav",
|
||||
"weapons/cbar_hitbod3.wav"
|
||||
};
|
||||
|
||||
EMIT_SOUND_DYN2(player->GetEdict(), CHAN_VOICE, bit_sound[RANDOM_LONG(0,2)], 1.0, ATTN_NORM, 0, PITCH_NORM);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// native ns_get_locationname(Float:x, Float:y, name[], len, lookup=0);
|
||||
static cell AMX_NATIVE_CALL ns_get_locationname(AMX *amx, cell *params)
|
||||
{
|
||||
vec3_t location;
|
||||
|
||||
|
||||
location.x=amx_ctof2(params[1]);
|
||||
location.y=amx_ctof2(params[2]);
|
||||
|
||||
if ((params[0] / sizeof(cell)) >= 5)
|
||||
{
|
||||
return MF_SetAmxString(amx,params[3],LocationMan.Lookup(location,params[5]),params[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return MF_SetAmxString(amx,params[3],LocationMan.Lookup(location,0),params[4]);
|
||||
}
|
||||
}
|
||||
// ns_lookup_title(const Key[], Output[], Size)
|
||||
static cell AMX_NATIVE_CALL ns_lookup_title(AMX *amx, cell *params)
|
||||
{
|
||||
// FIX: some keys have upper case characters; to fix i store all keys as lower case
|
||||
String Input(MF_GetAmxString(amx,params[1],0,NULL));
|
||||
|
||||
Input.toLower();
|
||||
|
||||
const char *Output=TitleMan.Lookup(Input);
|
||||
|
||||
if (Output==NULL) // not found
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return MF_SetAmxString(amx,params[2],Output,params[3]);
|
||||
};
|
||||
// ns_round_in_progress()
|
||||
static cell AMX_NATIVE_CALL ns_round_in_progress(AMX *amx, cell *params)
|
||||
{
|
||||
return GameMan.RoundInProgress();
|
||||
}
|
||||
// ns_get_spawn(team,number=0,Float:ret[3])
|
||||
static cell AMX_NATIVE_CALL ns_get_spawn(AMX *amx, cell *params)
|
||||
{
|
||||
return SpawnMan.Lookup(amx,params);
|
||||
}
|
||||
// ns_get_mask(id,MASK_*)
|
||||
static cell AMX_NATIVE_CALL ns_get_mask(AMX *amx, cell *params)
|
||||
{
|
||||
CreateEdict(amx,params[1],-1);
|
||||
|
||||
if (Entity->v.iuser4 & static_cast<int>(params[2]))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
// ns_set_mask(id,MASK_*,1 or 0)
|
||||
static cell AMX_NATIVE_CALL ns_set_mask(AMX *amx, cell *params)
|
||||
{
|
||||
CreateEdict(amx,params[1],-1);
|
||||
|
||||
if (static_cast<int>(params[3]) > 0)
|
||||
{
|
||||
if (Entity->v.iuser4 & static_cast<int>(params[2]))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Entity->v.iuser4 |= static_cast<int>(params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (Entity->v.iuser4 & static_cast<int>(params[2]))
|
||||
{
|
||||
Entity->v.iuser4 &= ~static_cast<int>(params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
// ns_popup(id (0 for all),"text",OnlyShowWithCLHelpOn=0)
|
||||
static cell AMX_NATIVE_CALL ns_popup(AMX *amx, cell *params)
|
||||
{
|
||||
GameMan.UpdateHudText2();
|
||||
|
||||
if (params[1])
|
||||
{
|
||||
CreatePlayerPointer(amx, params[1]);
|
||||
|
||||
if (!player->IsConnected())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
MESSAGE_BEGIN(MSG_ONE,GameMan.GetHudText2(),NULL,player->GetEdict());
|
||||
}
|
||||
else
|
||||
{
|
||||
MESSAGE_BEGIN(MSG_ALL,GameMan.GetHudText2());
|
||||
}
|
||||
|
||||
char msg[190];
|
||||
strncpy(&msg[0],MF_GetAmxString(amx,params[2],0,NULL),188);
|
||||
|
||||
WRITE_STRING(msg);
|
||||
WRITE_BYTE(params[3]);
|
||||
|
||||
MESSAGE_END();
|
||||
|
||||
return 1;
|
||||
}
|
||||
// ns_is_combat()
|
||||
static cell AMX_NATIVE_CALL ns_is_combat(AMX *amx, cell *params)
|
||||
{
|
||||
return GameMan.IsCombat();
|
||||
}
|
||||
/**
|
||||
* Pretty much a direct port of CheezyPeteza's unstick routine
|
||||
* from the old unstuck.amxx plugin. This is included here
|
||||
* to remove the engine requirement.
|
||||
* -
|
||||
* Return values:
|
||||
* 1 success
|
||||
* 0 no spot to move to
|
||||
* -1 invalid state (stunned/webbed)
|
||||
* -2 invalid class (commander/gorge)
|
||||
* -3 player is dead or a spectator
|
||||
* -4 player is invalid (unknown)
|
||||
* -5 player is invalid (disconnected)
|
||||
*/
|
||||
|
||||
inline int GetPlayerHullSize(CPlayer *Player, int PlayerClass)
|
||||
{
|
||||
switch (PlayerClass)
|
||||
{
|
||||
case CLASS_SKULK:
|
||||
case CLASS_GORGE:
|
||||
case CLASS_LERK:
|
||||
return static_cast<int>(head_hull);
|
||||
|
||||
case CLASS_FADE:
|
||||
case CLASS_JETPACK:
|
||||
case CLASS_HEAVY:
|
||||
case CLASS_MARINE:
|
||||
if (Player->GetPev()->button & IN_DUCK || Player->GetPev()->flags & FL_DUCKING)
|
||||
{
|
||||
return static_cast<int>(head_hull);
|
||||
}
|
||||
|
||||
return static_cast<int>(human_hull);
|
||||
|
||||
case CLASS_ONOS:
|
||||
if (Player->GetPev()->button & IN_DUCK || Player->GetPev()->flags & FL_DUCKING)
|
||||
{
|
||||
return static_cast<int>(human_hull);
|
||||
}
|
||||
|
||||
return static_cast<int>(large_hull);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
static cell AMX_NATIVE_CALL ns_unstick_player(AMX *amx, cell *params)
|
||||
{
|
||||
CreatePlayerPointer(amx,params[1]);
|
||||
|
||||
if (!player->IsConnected())
|
||||
{
|
||||
return -5;
|
||||
}
|
||||
|
||||
if (player->GetPev()->iuser4 & (MASK_ENSNARED | MASK_PLAYER_STUNNED))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int PlayerClass=player->GetClass();
|
||||
if (PlayerClass == CLASS_GESTATE || PlayerClass == CLASS_COMMANDER)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (PlayerClass == CLASS_DEAD || PlayerClass == CLASS_NOTEAM || PlayerClass == CLASS_UNKNOWN)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
int HullSize=GetPlayerHullSize(player, PlayerClass);
|
||||
|
||||
|
||||
if (HullSize==-1)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
|
||||
Vector OriginalOrigin=player->GetPev()->origin;
|
||||
|
||||
Vector NewOrigin;
|
||||
int Distance=params[2];
|
||||
int Attempts;
|
||||
TraceResult Result;
|
||||
|
||||
while (Distance < 1000)
|
||||
{
|
||||
Attempts=params[3];
|
||||
|
||||
while (Attempts--)
|
||||
{
|
||||
NewOrigin.x = RANDOM_FLOAT(OriginalOrigin.x - Distance,OriginalOrigin.x + Distance);
|
||||
NewOrigin.y = RANDOM_FLOAT(OriginalOrigin.y - Distance,OriginalOrigin.y + Distance);
|
||||
NewOrigin.z = RANDOM_FLOAT(OriginalOrigin.z - Distance,OriginalOrigin.z + Distance);
|
||||
|
||||
// (const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr);
|
||||
TRACE_HULL(NewOrigin, NewOrigin, 0, HullSize, player->GetEdict(), &Result);
|
||||
|
||||
if (Result.fInOpen && !Result.fAllSolid && !Result.fStartSolid)
|
||||
{
|
||||
SET_ORIGIN(player->GetEdict(),NewOrigin);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Distance += params[2];
|
||||
}
|
||||
|
||||
|
||||
return 0; // Couldn't be found
|
||||
}
|
||||
// Type: 131072 = DoT
|
||||
// ns_takedamage
|
||||
static cell AMX_NATIVE_CALL ns_takedamage(AMX *amx, cell *params)
|
||||
{
|
||||
// NASTY
|
||||
// Reinterprets pvPrivateData as CBaseEntity, then calls TakeDamage with the entvar of Inflictor, and Attacker, with the float value and damage type
|
||||
// The NS offset of TakeDamage hasn't changed from the HLSDK fortunately, so no offset digging is necessary
|
||||
return (reinterpret_cast<CBaseEntity *>(INDEXENT_NEW(params[1])->pvPrivateData))->TakeDamage(&(INDEXENT_NEW(params[2])->v),&(INDEXENT_NEW(params[3])->v),amx_ctof2(params[4]),static_cast<int>(params[5]));
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL ns_get_gameplay(AMX* amx, cell* params)
|
||||
{
|
||||
if (avhgameplay == NULL)
|
||||
{
|
||||
avhgameplay = FIND_ENTITY_BY_CLASSNAME(NULL, "avhgameplay");
|
||||
}
|
||||
if (avhgameplay == NULL ||
|
||||
avhgameplay->pvPrivateData == NULL) // Still null? Get out of here
|
||||
{
|
||||
return NSGame_CantTell;
|
||||
}
|
||||
|
||||
int ATeam /* i pity da foo */ = *reinterpret_cast<int*>(reinterpret_cast<char*>(avhgameplay->pvPrivateData) + MAKE_OFFSET(GAMEPLAY_TEAMA));
|
||||
int BTeam = *reinterpret_cast<int*>(reinterpret_cast<char*>(avhgameplay->pvPrivateData) + MAKE_OFFSET(GAMEPLAY_TEAMB));
|
||||
|
||||
if (ATeam == 2 && // alien
|
||||
BTeam == 2) // alien
|
||||
{
|
||||
return NSGame_AlienVAlien;
|
||||
}
|
||||
if (ATeam == 1 && // marine
|
||||
BTeam == 1) // marine
|
||||
{
|
||||
return NSGame_MarineVMarine;
|
||||
}
|
||||
if (ATeam == 1 && // marine
|
||||
BTeam == 2) // alien
|
||||
{
|
||||
return NSGame_MarineVAlien;
|
||||
}
|
||||
return NSGame_Unknown;
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEVELOPER_BUILD
|
||||
static cell AMX_NATIVE_CALL refmem(AMX *amx, cell *params)
|
||||
{
|
||||
return *(reinterpret_cast<int *>(params[1]));
|
||||
};
|
||||
static cell AMX_NATIVE_CALL setmem(AMX *amx, cell *params)
|
||||
{
|
||||
int *ptr=reinterpret_cast<int *>(params[1]);
|
||||
|
||||
*ptr=params[2];
|
||||
|
||||
return 1;
|
||||
};
|
||||
#endif
|
||||
|
||||
AMX_NATIVE_INFO general_natives[] = {
|
||||
|
||||
{ "user_kill", ns_user_kill }, // replacement natives
|
||||
{ "user_slap", ns_user_slap }, // since ClientKill is changed in NS
|
||||
|
||||
{ "ns_get_locationname", ns_get_locationname },
|
||||
{ "ns_lookup_title", ns_lookup_title },
|
||||
{ "ns_round_in_progress", ns_round_in_progress },
|
||||
{ "ns_get_spawn", ns_get_spawn },
|
||||
{ "ns_get_mask", ns_get_mask },
|
||||
{ "ns_set_mask", ns_set_mask },
|
||||
{ "ns_is_combat", ns_is_combat },
|
||||
{ "ns_unstick_player", ns_unstick_player },
|
||||
|
||||
{ "ns_popup", ns_popup },
|
||||
|
||||
{ "ns_takedamage", ns_takedamage},
|
||||
|
||||
{ "ns_get_gameplay", ns_get_gameplay },
|
||||
|
||||
#ifdef DEVELOPER_BUILD
|
||||
{ "refmem", refmem },
|
||||
{ "setmem", setmem },
|
||||
#endif
|
||||
|
||||
{ NULL, NULL }
|
||||
|
||||
};
|
||||
void AddNatives_General()
|
||||
{
|
||||
MF_AddNatives(general_natives);
|
||||
}
|
Reference in New Issue
Block a user