diff --git a/amxmodx/CLang.cpp b/amxmodx/CLang.cpp index 2a7263fb..0c0cba49 100755 --- a/amxmodx/CLang.cpp +++ b/amxmodx/CLang.cpp @@ -33,6 +33,7 @@ #include "amxmodx.h" #include "CLang.h" #include "format.h" +#include "amxmod_compat.h" #ifdef __linux__ #define _snprintf snprintf @@ -287,7 +288,23 @@ char * CLangMngr::FormatAmxString(AMX *amx, cell *params, int parm, int &len) static char outbuf[4096]; cell *addr = get_amxaddr(amx, params[parm++]); - len = atcprintf(outbuf, sizeof(outbuf)-1, addr, amx, params, &parm); + if (amx->flags & AMX_FLAG_OLDFILE) + { + if (*addr & BCOMPAT_TRANSLATE_BITS) + { + const char *key, *def; + if (!translate_bcompat(amx, addr, &key, &def)) + { + goto normal_string; + } + len = atcprintf(outbuf, sizeof(outbuf)-1, def, amx, params, &parm); + } else { + goto normal_string; + } + } else { +normal_string: + len = atcprintf(outbuf, sizeof(outbuf)-1, addr, amx, params, &parm); + } return outbuf; } diff --git a/amxmodx/CModule.cpp b/amxmodx/CModule.cpp index 59b824b2..803f1ff7 100755 --- a/amxmodx/CModule.cpp +++ b/amxmodx/CModule.cpp @@ -89,6 +89,7 @@ void CModule::clear(bool clearFilename) m_DestroyableIndexes.clear(); m_Natives.clear(); + m_NewNatives.clear(); } bool CModule::attachMetamod(const char *mmfile, PLUG_LOADTIME now) diff --git a/amxmodx/CModule.h b/amxmodx/CModule.h index 842a503c..5f7c2030 100755 --- a/amxmodx/CModule.h +++ b/amxmodx/CModule.h @@ -117,6 +117,7 @@ public: void CallPluginsUnloading(); CVector m_Natives; + CVector m_NewNatives; // Natives for new (AMXX, not AMX) plugins only CVector m_DestroyableIndexes; }; diff --git a/amxmodx/CPlugin.cpp b/amxmodx/CPlugin.cpp index 96048268..6ad511f6 100755 --- a/amxmodx/CPlugin.cpp +++ b/amxmodx/CPlugin.cpp @@ -447,7 +447,8 @@ char *CPluginMngr::ReadIntoOrFromCache(const char *file, size_t &bufsize) pl->file = new CAmxxReader(file, sizeof(cell)); pl->buffer = NULL; - if (pl->file->GetStatus() != CAmxxReader::Err_None) + if (pl->file->GetStatus() != CAmxxReader::Err_None || + pl->file->IsOldFile()) { delete pl->file; delete pl; diff --git a/amxmodx/Makefile b/amxmodx/Makefile index c22b9325..934edaf5 100755 --- a/amxmodx/Makefile +++ b/amxmodx/Makefile @@ -19,7 +19,8 @@ OBJECTS = meta_api.cpp CFile.cpp CVault.cpp vault.cpp float.cpp file.cpp modules srvcmd.cpp strptime.cpp amxcore.cpp amxtime.cpp power.cpp amxxlog.cpp fakemeta.cpp \ amxxfile.cpp CLang.cpp md5.cpp emsg.cpp CForward.cpp CPlugin.cpp CModule.cpp \ CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \ - optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp + optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \ + amxmod_compat.cpp LINK = -lgcc -static-libgcc diff --git a/amxmodx/amxmod_compat.cpp b/amxmodx/amxmod_compat.cpp new file mode 100644 index 00000000..2d2f6fd1 --- /dev/null +++ b/amxmodx/amxmod_compat.cpp @@ -0,0 +1,136 @@ +#include "amxmodx.h" +#include "amxmod_compat.h" +#include "format.h" + +struct translate_result +{ + int suki; + int dest; + int lang; +}; + +CVector g_tr_results; +CStack g_old_ids; + +bool GetTranslation(int id, int &key, int &dest, int &lang) +{ + if (id < 0 || (unsigned int)id > g_tr_results.size()) + { + return false; + } + + translate_result *pRes = g_tr_results[id]; + + key = pRes->suki; + dest = pRes->dest; + lang = pRes->lang; + + g_old_ids.push((size_t)id); + + return true; +} + +void ClearTransCache() +{ + for (size_t i=0; i(*source); + trans &= ~BCOMPAT_TRANSLATE_BITS; + int key, _dest, lang; + if (!GetTranslation(trans, key, _dest, lang)) + { + return false; + } + + cell amx_addr, *phys_addr; + if (amx_Allot(amx, 3, &amx_addr, &phys_addr) != AMX_ERR_NONE) + { + return false; + } + + if (_dest == -1) + { + *phys_addr = LANG_PLAYER; + } else if (_dest == 0) { + *phys_addr = LANG_SERVER; + } else if (lang >= 0 && lang < g_langMngr.GetLangsNum()) { + const char *name = g_langMngr.GetLangName(lang); + phys_addr[0] = static_cast(name[0]); + phys_addr[1] = static_cast(name[1]); + phys_addr[2] = static_cast('\0'); + } else { + *phys_addr = LANG_SERVER; + } + + //not optimized but it works, eh + //if someone cares they can make a translate() wrapper that takes the key # in directly + const char *r_key = g_langMngr.GetKey(key); + const char *def = translate(amx, amx_addr, r_key); + if (!def) + { + def = r_key; + } + amx_Release(amx, amx_addr); + + *_key = g_langMngr.GetKey(key); + *_def = def; + + return true; +} + +static cell AMX_NATIVE_CALL amx_translate(AMX *amx, cell *params) +{ + int len; + char *key = get_amxstring(amx, params[1], 0, len); + + translate_result *pRes; + size_t id; + if (g_old_ids.empty()) + { + pRes = new translate_result; + id = g_tr_results.size(); + g_tr_results.push_back(pRes); + } else { + if (g_tr_results.size() >= BCOMPAT_TRANSLATE_MAX) + { + LogError(amx, AMX_ERR_NATIVE, "Exceeded bcompat translation limit of %d!", BCOMPAT_TRANSLATE_MAX); + return 0; + } + id = g_old_ids.front(); + g_old_ids.pop(); + pRes = g_tr_results[id]; + } + + pRes->suki = g_langMngr.GetKeyEntry(key); + + //Some AMX Mod plugins do not register everything they need. Prevent a crash. + if (pRes->suki == -1) + { + pRes->suki = g_langMngr.AddKeyEntry(key); + } + + pRes->dest = params[2]; + pRes->lang = params[3]; + + return (cell)((unsigned int)BCOMPAT_TRANSLATE_BITS | (unsigned int)id); +} + +AMX_NATIVE_INFO g_BcompatNatives[] = +{ + {"translate", amx_translate}, + + {NULL, NULL}, +}; + diff --git a/amxmodx/amxmod_compat.h b/amxmodx/amxmod_compat.h new file mode 100644 index 00000000..cd2bd779 --- /dev/null +++ b/amxmodx/amxmod_compat.h @@ -0,0 +1,12 @@ +#ifndef _INCLUDE_AMXMOD_CORE_COMPAT_H +#define _INCLUDE_AMXMOD_CORE_COMPAT_H + +#define BCOMPAT_TRANSLATE_BITS 0xFFFFF400 +#define BCOMPAT_TRANSLATE_MAX 0x400 + +bool GetTranslation(int id, int &key, int &dest, int &lang); +void ClearTransCache(); + +extern AMX_NATIVE_INFO g_BcompatNatives[]; + +#endif //_INCLUDE_AMXMOD_CORE_COMPAT_H diff --git a/amxmodx/debugger.cpp b/amxmodx/debugger.cpp index e9b9050d..c7c275b5 100755 --- a/amxmodx/debugger.cpp +++ b/amxmodx/debugger.cpp @@ -608,6 +608,7 @@ const char *Debugger::_GetFilename() void Debugger::FmtGenericMsg(AMX *amx, int error, char buffer[], size_t maxLength) { const char *filename = ""; + char native[sNAMEMAX+1]; CList::iterator a = g_loadedscripts.find(amx); if (a) @@ -625,6 +626,9 @@ void Debugger::FmtGenericMsg(AMX *amx, int error, char buffer[], size_t maxLengt if (error == AMX_ERR_EXIT) { _snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - %s", error, filename, GenericError(AMX_ERR_EXIT)); + } else if (error == AMX_ERR_NATIVE) { + amx_GetNative(amx, (int)amx->usertags[UT_NATIVE], native); + _snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") (native \"%s\") - debug not enabled!", error, filename, native); } else { _snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - debug not enabled!", error, filename); } diff --git a/amxmodx/float.cpp b/amxmodx/float.cpp index 64fae73d..f21d94fb 100755 --- a/amxmodx/float.cpp +++ b/amxmodx/float.cpp @@ -424,6 +424,54 @@ static cell AMX_NATIVE_CALL n_floatatan2(AMX *amx, cell *params) return amx_ftoc(fC); } +#if defined __BORLANDC__ || defined __WATCOMC__ + #pragma argsused +#endif +/* Added by DS */ +static cell AMX_NATIVE_CALL n_floatsinh(AMX *amx, cell *params) +{ + /* + * params[1] = angle + * params[2] = radix + */ + REAL fA = amx_ctof(params[1]); + fA = ToRadians(fA, params[2]); + fA = sinh(fA); + return amx_ftoc(fA); +} + +#if defined __BORLANDC__ || defined __WATCOMC__ + #pragma argsused +#endif +/* Added by DS */ +static cell AMX_NATIVE_CALL n_floatcosh(AMX *amx, cell *params) +{ + /* + * params[1] = angle + * params[2] = radix + */ + REAL fA = amx_ctof(params[1]); + fA = ToRadians(fA, params[2]); + fA = cosh(fA); + return amx_ftoc(fA); +} + +#if defined __BORLANDC__ || defined __WATCOMC__ + #pragma argsused +#endif +/* Added by DS */ +static cell AMX_NATIVE_CALL n_floattanh(AMX *amx, cell *params) +{ + /* + * params[1] = angle + * params[2] = radix + */ + REAL fA = amx_ctof(params[1]); + fA = ToRadians(fA, params[2]); + fA = tanh(fA); + return amx_ftoc(fA); +} + #if defined __BORLANDC__ || defined __WATCOMC__ #pragma argsused #endif @@ -456,6 +504,9 @@ AMX_NATIVE_INFO float_Natives[] = { { "floatacos", n_floatacos }, { "floatatan", n_floatatan }, { "floatatan2", n_floatatan2 }, + { "floatsinh", n_floatsinh }, + { "floatcosh", n_floatcosh }, + { "floattanh", n_floattanh }, { NULL, NULL } /* terminator */ }; diff --git a/amxmodx/format.cpp b/amxmodx/format.cpp index b2e788db..441ab2c8 100644 --- a/amxmodx/format.cpp +++ b/amxmodx/format.cpp @@ -1,5 +1,6 @@ #include "amxmodx.h" #include "format.h" +#include "amxmod_compat.h" //Adapted from Quake3's vsprintf // thanks to cybermind for linking me to this :) @@ -422,6 +423,24 @@ reswitch: break; case 's': CHECK_ARGS(0); + if (amx->flags & AMX_FLAG_OLDFILE) + { + cell *addr = get_amxaddr(amx, params[arg]); + if (*addr & BCOMPAT_TRANSLATE_BITS) + { + const char *key, *def; + if (!translate_bcompat(amx, addr, &key, &def)) + { + goto break_to_normal_string; + } + arg++; + size_t written = atcprintf(buf_p, llen, def, amx, params, &arg); + buf_p += written; + llen -= written; + break; + } + } +break_to_normal_string: AddString(&buf_p, llen, get_amxaddr(amx, params[arg]), width, prec); arg++; break; diff --git a/amxmodx/format.h b/amxmodx/format.h index a1441a64..a9c6f630 100644 --- a/amxmodx/format.h +++ b/amxmodx/format.h @@ -5,4 +5,7 @@ template size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param); +const char *translate(AMX *amx, cell amxaddr, const char *key); +bool translate_bcompat(AMX *amx, cell *source, const char **_key, const char **_def); + #endif //_INCLUDE_FORMATTING_H diff --git a/amxmodx/meta_api.cpp b/amxmodx/meta_api.cpp index 6763d433..9f859503 100755 --- a/amxmodx/meta_api.cpp +++ b/amxmodx/meta_api.cpp @@ -45,6 +45,7 @@ #include "optimizer.h" #include "libraries.h" #include "messages.h" +#include "amxmod_compat.h" plugin_info_t Plugin_info = { @@ -357,6 +358,14 @@ int C_Spawn(edict_t *pent) get_localinfo("amxx_configsdir", "addons/amxmodx/configs"); get_localinfo("amxx_customdir", "addons/amxmodx/custom"); + // make sure bcompat localinfos are set + get_localinfo("amx_basedir", "addons/amxmodx"); + get_localinfo("amx_configdir", "addons/amxmodx/configs"); + get_localinfo("amx_langdir", "addons/amxmodx/data/amxmod-lang"); + get_localinfo("amx_modulesdir", "addons/amxmodx/modules"); + get_localinfo("amx_pluginsdir", "addons/amxmodx/plugins"); + get_localinfo("amx_logdir", "addons/amxmodx/logs"); + char map_pluginsfile_path[256]; // ###### Load modules @@ -619,6 +628,7 @@ void C_ServerDeactivate_Post() g_xvars.clear(); g_plugins.clear(); ClearPluginLibraries(); + ClearTransCache(); modules_callPluginsUnloaded(); ClearMessages(); diff --git a/amxmodx/modules.cpp b/amxmodx/modules.cpp index e220ecf2..a0b638ac 100755 --- a/amxmodx/modules.cpp +++ b/amxmodx/modules.cpp @@ -48,6 +48,7 @@ #include "binlog.h" #include "libraries.h" #include "messages.h" +#include "amxmod_compat.h" CList g_modules; CList g_loadedscripts; @@ -165,6 +166,7 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64 *error = 0; size_t bufSize; *program = (void *)g_plugins.ReadIntoOrFromCache(filename, bufSize); + bool oldfile = false; if (!*program) { CAmxxReader reader(filename, PAWN_CELL_SIZE / 8); @@ -218,6 +220,8 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64 strcpy(error, "Unknown error"); return (amx->error = AMX_ERR_NOTFOUND); } + + oldfile = reader.IsOldFile(); } else { g_plugins.InvalidateFileInCache(filename, false); } @@ -369,6 +373,17 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64 } #endif + if (oldfile) + { + amx->flags |= AMX_FLAG_OLDFILE; + } else { + cell addr; + if (amx_FindPubVar(amx, "__b_old_plugin", &addr) == AMX_ERR_NONE) + { + amx->flags |= AMX_FLAG_OLDFILE; + } + } + CScript* aa = new CScript(amx, *program, filename); g_loadedscripts.put(aa); @@ -542,6 +557,12 @@ int set_amxnatives(AMX* amx, char error[128]) { amx_Register(amx, cm->m_Natives[i], -1); } + + for (size_t i = 0; i < cm->m_NewNatives.size(); i++) + { + if (!(amx->flags & AMX_FLAG_OLDFILE)) + amx_Register(amx, cm->m_NewNatives[i], -1); + } } amx_Register(amx, string_Natives, -1); @@ -557,6 +578,11 @@ int set_amxnatives(AMX* amx, char error[128]) amx_Register(amx, msg_Natives, -1); amx_Register(amx, vector_Natives, -1); amx_Register(amx, g_SortNatives, -1); + + if (amx->flags & AMX_FLAG_OLDFILE) + { + amx_Register(amx, g_BcompatNatives, -1); + } //we're not actually gonna check these here anymore amx->flags |= AMX_FLAG_PRENIT; @@ -1178,6 +1204,18 @@ int MNF_AddNatives(AMX_NATIVE_INFO* natives) return TRUE; } +int MNF_AddNewNatives(AMX_NATIVE_INFO *natives) +{ + CList::iterator a = g_modules.begin(); + + if (!g_CurrentlyCalledModule || g_ModuleCallReason != ModuleCall_Attach) + return FALSE; // may only be called from attach + + g_CurrentlyCalledModule->m_NewNatives.push_back(natives); + + return TRUE; +} + const char *MNF_GetModname(void) { // :TODO: Do we have to do this?? @@ -1870,6 +1908,7 @@ void Module_CacheFunctions() // Natives / Forwards REGISTER_FUNC("AddNatives", MNF_AddNatives) + REGISTER_FUNC("AddNewNatives", MNF_AddNewNatives) REGISTER_FUNC("RaiseAmxError", amx_RaiseError) REGISTER_FUNC("RegisterForward", registerForward) REGISTER_FUNC("RegisterSPForward", registerSPForward) diff --git a/amxmodx/string.cpp b/amxmodx/string.cpp index 68ed9035..5fbaad38 100755 --- a/amxmodx/string.cpp +++ b/amxmodx/string.cpp @@ -33,6 +33,7 @@ #include "amxmodx.h" #include "format.h" #include "binlog.h" +#include "amxmod_compat.h" const char* stristr(const char* str, const char* substr) { @@ -115,8 +116,21 @@ extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, in register char *dest = destination; char *start = dest; - while (maxlen-- && *source) - *dest++=(char)(*source++); + if ( (amx->flags & AMX_FLAG_OLDFILE) && + (*source & BCOMPAT_TRANSLATE_BITS) ) + { + const char *def, *key; + if (!translate_bcompat(amx, source, &key, &def)) + { + goto normal_string; + } + while (maxlen-- && *def) + *dest++=(*source++); + } else { +normal_string: + while (maxlen-- && *source) + *dest++=(char)(*source++); + } *dest = '\0'; @@ -132,16 +146,29 @@ extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, in return dest - start; } -char* get_amxstring(AMX *amx, cell amx_addr, int id, int& len) +char *get_amxstring(AMX *amx, cell amx_addr, int id, int& len) { static char buffor[4][3072]; register cell* source = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr)); register char* dest = buffor[id]; char* start = dest; - - while ((*dest++=(char)(*source++))); - len = --dest - start; + if ( (amx->flags & AMX_FLAG_OLDFILE) && + (*source & BCOMPAT_TRANSLATE_BITS) ) + { + const char *def, *key; + if (!translate_bcompat(amx, source, &key, &def)) + { + goto normal_string; + } + while ( (*dest++ = (*def++)) ); + len = --dest - start; + } else { +normal_string: + while ((*dest++=(char)(*source++))); + + len = --dest - start; + } #if defined BINLOG_ENABLED if (g_binlog_level & 2) diff --git a/dlls/engine/Makefile b/dlls/engine/Makefile index 049bbae8..51f60c55 100755 --- a/dlls/engine/Makefile +++ b/dlls/engine/Makefile @@ -14,7 +14,8 @@ NAME = engine BIN_SUFFIX_32 = amxx_i386.so BIN_SUFFIX_64 = amxx_amd64.so -OBJECTS = amxxmodule.cpp amxxapi.cpp engine.cpp entity.cpp globals.cpp forwards.cpp +OBJECTS = amxxmodule.cpp amxxapi.cpp engine.cpp entity.cpp globals.cpp forwards.cpp \ + amxmod_compat.cpp LINK = diff --git a/dlls/engine/amxmod_compat.cpp b/dlls/engine/amxmod_compat.cpp new file mode 100644 index 00000000..d3ca40dc --- /dev/null +++ b/dlls/engine/amxmod_compat.cpp @@ -0,0 +1,453 @@ +#include "engine.h" +#include + +static cvar_t *sv_knockback1 = NULL; +static cvar_t *sv_knockback2 = NULL; +static cvar_t *sv_friendlyfire = NULL; +static bool g_ff_check = false; +static bool g_kb1_check = false; +static bool g_kb2_check = false; +static int gmsgDamage = 0; +static int gmsgDeathMsg = 0; +static int gmsgScoreInfo = 0; + +//From VexdUM (AMX Mod 2006.2) +//This is not exposed, and is only provided as a compatibility helper. +BOOL is_breakable(edict_t* pBreak) +{ + if (FStrEq("func_breakable", STRING(pBreak->v.classname)) + || FStrEq("func_pushable", STRING(pBreak->v.classname)) + && pBreak->v.spawnflags & SF_PUSH_BREAKABLE) + { + return true; + } + + return false; +} + +//From VexdUM (AMX Mod 2006.2) +//This is not exposed, and is only provided as a compatibility helper. +BOOL is_monster(edict_t* pMonster) +{ + if(pMonster->v.flags & FL_MONSTER) + { + return true; + } + + return false; +} + +//From VexdUM (AMX Mod 2006.2) +// Damage Monsters +void hurt_monster(edict_t* pMonster, float dmg, int bit, const float *origin) +{ + int mdmg = (int)pMonster->v.health; + pMonster->v.health -= dmg; + + // No need to create a trigger_hurt unless we are going to kill the monster ;) + if((int)pMonster->v.health < 1) + { + int hurt = MAKE_STRING("trigger_hurt"); + char hbit[16]; + char horigin[16]; + snprintf(hbit, 15, "%i", bit); + snprintf(horigin, 15, "%f %f %f", origin[0], origin[1], origin[2]); + + edict_t* pEntity = CREATE_NAMED_ENTITY(hurt); + KeyValueData pkvd1; + pkvd1.szClassName = "trigger_hurt"; + pkvd1.szKeyName = "dmg"; + pkvd1.szValue = "1.0"; + pkvd1.fHandled = FALSE; + MDLL_KeyValue(pEntity, &pkvd1); + + KeyValueData pkvd2; + pkvd2.szClassName = "trigger_hurt"; + pkvd2.szKeyName = "damagetype"; + pkvd2.szValue = hbit; + pkvd2.fHandled = FALSE; + MDLL_KeyValue(pEntity, &pkvd2); + + KeyValueData pkvd3; + pkvd3.szClassName = "trigger_hurt"; + pkvd3.szKeyName = "origin"; + pkvd3.szValue = horigin; + pkvd3.fHandled = FALSE; + MDLL_KeyValue(pEntity, &pkvd3); + + MDLL_Spawn(pEntity); + MDLL_Touch(pEntity, pMonster); + REMOVE_ENTITY(pEntity); + } + mdmg -= (int)pMonster->v.health; + //~dvander - Note, not porting the forward until this function is known to be truly wrapped + //g_forwards.executeForward(FF_MonsterHurt, ENTINDEX(pMonster), ENTINDEX(pMonster->v.dmg_inflictor), mdmg); +} + +//From VexdUM (AMX Mod 2006.2) +//This appears to be from the HLSDK CBasePlayer::TakeDamage() function. +//This is not exposed, and is only provided as a compatibility helper. +float ArmorDamage(edict_t* pVictim, float dmg, int bit) +{ + float flRatio = 0.2; + float flBonus = 0.5; + if(bit & DMG_BLAST) + { + // blasts damage armor more. + flBonus *= 2; + } + if(pVictim->v.armorvalue && !(bit & (DMG_FALL | DMG_DROWN))) + { + // armor doesn't protect against fall or drown damage! + float flNew = dmg * flRatio; + float flArmor = (dmg - flNew) * flBonus; + + // Does this use more armor than we have? + if(flArmor > pVictim->v.armorvalue) + { + flArmor = pVictim->v.armorvalue; + flArmor *= (1/flBonus); + flNew = dmg - flArmor; + pVictim->v.armorvalue = 0; + } else { + pVictim->v.armorvalue -= flArmor; + } + dmg = flNew; + } + // Lets knock the view about abit + pVictim->v.punchangle.x = -4; + return dmg; +} + +// Death emulation +//This is not exposed, and is only provided as a compatibility helper. +void Death(edict_t* pVictim, edict_t* pKiller, const char* weapon, int hs) +{ + + if (!gmsgDeathMsg) + { + gmsgDeathMsg = GET_USER_MSG_ID(PLID, "DeathMsg", NULL); + } + + if (!gmsgScoreInfo) + { + gmsgScoreInfo = GET_USER_MSG_ID(PLID, "ScoreInfo", NULL); + } + + // Make sure an entity is allowed to take damage + if(pVictim->v.takedamage > DAMAGE_NO) + { + // Breakable Check + if(is_breakable(pVictim)) + { + MDLL_Use(pVictim, pKiller); + } + // Monster Check + if (is_monster(pVictim)) + { + pVictim->v.dmg_inflictor = pKiller; + float dmg = pVictim->v.health; + int bit = DMG_BULLET; + const float *origin = pVictim->v.origin; + hurt_monster(pVictim, dmg, bit, origin); + } + // Player Check + if (pVictim->v.flags & (FL_CLIENT | FL_FAKECLIENT)) + { + pVictim->v.dmg_inflictor = pKiller; + edict_t* inflictor = pKiller->v.owner; + int inflictorId = FNullEnt(inflictor) ? ENTINDEX(inflictor) : 0; + + // See if it is a player attacking with a default weapon + if (pKiller->v.flags & (FL_CLIENT | FL_FAKECLIENT)) + { + // We only modify the weapon if it = 0, otherwise its been specified + if(strcmp(weapon, "") == 0) + { + char view_weapon[64]; + // Get the name from the view model + weapon = STRING(pKiller->v.viewmodel); + + // Strip out the beginning of the viewmodel (models/v_) + if(strncmp(weapon, "models/v_", 9) == 0) + { + strcpy(view_weapon, weapon + 9); + } + + // Strip out the end of viewmodel (.mdl) + view_weapon[strlen(view_weapon) - 4] = '\0'; + weapon = view_weapon; + } + // See if its an entity attacking, if so lets find its owner + } else if (inflictorId >= 1 && inflictorId <= gpGlobals->maxClients) { + // We only modify the weapon if it = 0, otherwise its been specified + if(strcmp(weapon, "") == 0) + { + weapon = STRING(pKiller->v.classname); + // Strip out the default part of weapon name (HLSDK) + if(strncmp(weapon, "weapon_", 7) == 0) + { + weapon += 7; + } else if(strncmp(weapon, "monster_", 8) == 0) { + weapon += 8; + } else if(strncmp(weapon, "func_", 5) == 0) { + weapon += 5; + } + } + // Check to see if the victim is the owner + if(inflictor == pVictim) + { + pKiller = pVictim; + } else { + pKiller = inflictor; + } + } + // Send the Death Event + int killerId = ENTINDEX(pKiller); + int victimId = ENTINDEX(pVictim); + MESSAGE_BEGIN( MSG_ALL, gmsgDeathMsg ); + WRITE_BYTE( killerId > gpGlobals->maxClients ? 0 : killerId ); + WRITE_BYTE( victimId ); + WRITE_BYTE( hs ); + WRITE_STRING( weapon ); + MESSAGE_END(); + // Log this kill + if(pVictim == pKiller) + { + // killed self + UTIL_LogPrintf("\"%s<%i><%s><%s>\" killed self with \"%s\"\n", + STRING( pVictim->v.netname ), + GETPLAYERUSERID( pVictim ), + GETPLAYERAUTHID( pVictim ), + MF_GetPlayerTeam(victimId), + weapon ); + // Killed by another player + } else if(pKiller->v.flags & (FL_CLIENT | FL_FAKECLIENT)) { + UTIL_LogPrintf("\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\"\n", + STRING( pKiller->v.netname ), + GETPLAYERUSERID( pKiller ), + GETPLAYERAUTHID( pKiller ), + MF_GetPlayerTeam(killerId), + STRING( pVictim->v.netname ), + GETPLAYERUSERID( pVictim ), + GETPLAYERAUTHID( pVictim ), + MF_GetPlayerTeam(victimId), + weapon); + + int killerTeam = MF_GetPlayerTeamID(killerId); + int victimTeam = MF_GetPlayerTeamID(victimId); + if (killerTeam != victimTeam) + { + // Give Killer credit for this kill + pKiller->v.frags += 1; + } else { + pKiller->v.frags -= 1; + } + // Update the scoreboard for the killer + if (gmsgScoreInfo) + { + MESSAGE_BEGIN(MSG_ALL, gmsgScoreInfo); + WRITE_BYTE( killerId ); + WRITE_SHORT( (int)pKiller->v.frags ); + WRITE_SHORT( MF_GetPlayerDeaths(killerId) ); + WRITE_SHORT( 0 ); + WRITE_SHORT( MF_GetPlayerTeamID(killerId) ); + MESSAGE_END(); + } + // Give Victim back 1 point since they didn't kill themselves + pVictim->v.frags += 1; + } + // Killed by something else? + else { + UTIL_LogPrintf( "\"%s<%i><%s><%s>\" killed by \"%s\"\n", + STRING( pVictim->v.netname ), + GETPLAYERUSERID( pVictim ), + GETPLAYERAUTHID( pVictim ), + MF_GetPlayerTeam(victimId), + weapon ); + // Give Victim back 1 point since they didn't commit suicide + pVictim->v.frags += 1; + } +#if 0 + //still a todo on this one + gInfo.logBlock = true; +#endif + int opt = BLOCK_ONCE; + MF_MessageBlock(MSGBLOCK_SET, gmsgDeathMsg, &opt); + // Kill the client, since the relevent logging blocks are in place + MDLL_ClientKill(pVictim); + // Restore the old message type + MF_MessageBlock(MSGBLOCK_SET, gmsgDeathMsg, &opt); + // Show the Victim the killing location + pVictim->v.iuser3 = (killerId > gpGlobals->maxClients) ? 0 : killerId; + } + } +} + +// Damage emulation +// From VexdUM (AMX Mod 2006.2) +//This is not exposed, and is only provided as a compatibility helper. +void Damage(edict_t *pVictim, + edict_t *pAttacker, + const float *origin, + float dmg, + int bit, + const char *weapon, + int hs) +{ + if (!g_ff_check && !sv_friendlyfire) + { + sv_friendlyfire = CVAR_GET_POINTER("sv_friendlyfire"); + g_ff_check = true; + } + + if (!gmsgDamage) + { + gmsgDamage = GET_USER_MSG_ID(PLID, "Damage", NULL); + } + + // Make sure an entity is allowed to take damage + if(pVictim->v.takedamage > DAMAGE_NO) + { + // Breakable Check + if(is_breakable(pVictim) && (int)dmg > 0) + { + MDLL_Use(pVictim, pAttacker); + } + // Monster Check + if(is_monster(pVictim) && (int)dmg > 0) + { + pVictim->v.dmg_inflictor = pAttacker; + hurt_monster(pVictim, dmg, bit, origin); + } + // Player Check + if(pVictim->v.flags & (FL_CLIENT | FL_FAKECLIENT)) + { + int AttackerId = ENTINDEX(pAttacker); + int AttackerOwnerId = ENTINDEX(pAttacker->v.owner); + int VictimId = ENTINDEX(pVictim); + int vTeam = MF_GetPlayerTeamID(VictimId); + int aTeam = 0; + if (AttackerId >= 1 && AttackerId <= gpGlobals->maxClients) + { + aTeam = MF_GetPlayerTeamID(AttackerId); + } else if (AttackerOwnerId >= 1 && AttackerOwnerId <= gpGlobals->maxClients) { + aTeam = MF_GetPlayerTeamID(AttackerOwnerId); + } + if((sv_friendlyfire && (int)sv_friendlyfire->value) || (vTeam != aTeam)) + { + // Recalculate the damage since we might have armor + dmg = ArmorDamage(pVictim, dmg, bit); + // Only allow damage to process if more than 0.5 + if((int)dmg > 0) + { + // Setting to externally flag who last attacked the Victim, pretty neat huh? + pVictim->v.dmg_inflictor = pAttacker; + pVictim->v.dmg_take += dmg; + // Register the Damage Event + MESSAGE_BEGIN( MSG_ONE, gmsgDamage, NULL, pVictim ); + WRITE_BYTE( (int)pVictim->v.dmg_save ); + WRITE_BYTE( (int)pVictim->v.dmg_take ); + WRITE_LONG( bit ); + WRITE_COORD( origin[0] ); + WRITE_COORD( origin[1] ); + WRITE_COORD( origin[2] ); + MESSAGE_END(); + + if((int)dmg >= (int)pVictim->v.health) + { + // Kill the victim + pVictim->v.health = 0.0; + // Send info to Death system + Death(pVictim, pAttacker, weapon, hs); + }else { + // Take health away from victim + pVictim->v.health -= dmg; + } + } + } + } + } +} + +// Radius Damage emulation - +// From VexdUM (AMX Mod 2006.2) +//This is not exposed, and is only provided as a compatibility helper. +void RadiusDamage_AMXMod_Base(edict_t *pAttacker, + float dmg, + Vector vecSrc, + float rad, + int bit, + const char *weapon, + int hs) +{ + edict_t *pTarget = NULL; + TraceResult tr; + float falloff; + Vector vecSpot; + Vector vecSee; + + if (!g_kb1_check && !sv_knockback1) + { + sv_knockback1 = CVAR_GET_POINTER("sv_knockback1"); + g_kb1_check = true; + } + if (!g_kb2_check && !sv_knockback2) + { + sv_knockback2 = CVAR_GET_POINTER("sv_knockback2"); + g_kb2_check = true; + } + + if(rad > 0.0) + { + falloff = dmg / rad; + } else { + falloff = 1.0; + } + vecSrc.z += 1; // In case grenade is lying on the ground + + int hitId; + int targetId; + + while ((pTarget = UTIL_FindEntityInSphere(pTarget, vecSrc, rad)) != NULL) + { + // Make sure an entity is allowed to take damage + if (pTarget->v.takedamage > DAMAGE_NO) + { + //none of this code was working so I simplified it + //damage doesn't check for visibility now (it probably shouldn't anyway) + //for this to work it seems like an exception needs to be made for world OR + // the spot/see things aren't being calculated right. +#if 0 + vecSpot = (pTarget->v.absmin + pTarget->v.absmax) * 0.5; + vecSee = (pAttacker->v.absmin + pAttacker->v.absmax) * 0.5; + TRACE_LINE(vecSee, vecSpot, FALSE, pAttacker, &tr); + // Explosion can 'see' this entity, so hurt them! +#endif + TRACE_LINE(vecSrc, pTarget->v.origin, FALSE, pAttacker, &tr); + hitId = ENTINDEX(tr.pHit); + targetId = ENTINDEX(pTarget); + if(tr.flFraction < 1.0 || (hitId == targetId)) + { + // Work out the distance between impact and entity + float dist = (tr.vecEndPos - vecSrc).Length() * falloff; + // Damage algorithm, its just that easy :) + dmg -= dist; + // Knockback Effect + if(pTarget->v.flags & (FL_CLIENT | FL_FAKECLIENT) && (bit & (DMG_BLAST | DMG_CLUB | DMG_SHOCK | DMG_SONIC | DMG_ENERGYBEAM | DMG_MORTAR))) + { + Vector vecPush = (pTarget->v.origin - (pAttacker->v.absmin + pAttacker->v.absmax) * 0.5).Normalize(); + if(dmg < 60.0) + { + pTarget->v.velocity = pTarget->v.velocity + vecPush * dmg * (sv_knockback1 ? sv_knockback1->value : 1.0f); + } else { + pTarget->v.velocity = pTarget->v.velocity + vecPush * dmg * (sv_knockback2 ? sv_knockback2->value : 1.0f); + } + } + // Send info to Damage system + Damage(pTarget, pAttacker, vecSrc, dmg, bit, weapon, hs); + } + } + } + pTarget = NULL; +} diff --git a/dlls/engine/amxmod_compat.h b/dlls/engine/amxmod_compat.h new file mode 100644 index 00000000..5ae98424 --- /dev/null +++ b/dlls/engine/amxmod_compat.h @@ -0,0 +1,25 @@ +#ifndef _INCLUDE_ENGINE_AMXMOD_BCOMPAT_H_ +#define _INCLUDE_ENGINE_AMXMOD_BCOMPAT_H_ + +BOOL is_breakable(edict_t* pBreak); +BOOL is_monster(edict_t* pMonster); +void hurt_monster(edict_t* pMonster, float dmg, int bit, const float *origin); +float ArmorDamage(edict_t* pVictim, float dmg, int bit); +void Death(edict_t* pVictim, edict_t* pKiller, const char* weapon, int hs); +void Damage(edict_t *pVictim, + edict_t *pAttacker, + const float *origin, + float dmg, + int bit, + const char *weapon, + int hs); +void RadiusDamage_AMXMod_Base(edict_t *pAttacker, + float dmg, + Vector vecSrc, + float rad, + int bit, + const char *weapon, + int hs); + +#endif //_INCLUDE_ENGINE_AMXMOD_BCOMPAT_H_ + diff --git a/dlls/engine/amxxapi.cpp b/dlls/engine/amxxapi.cpp index 750b73c8..5cf1a9ab 100755 --- a/dlls/engine/amxxapi.cpp +++ b/dlls/engine/amxxapi.cpp @@ -37,7 +37,9 @@ void OnAmxxAttach() CmdStartForward = 0; StartFrameForward = 0; MF_AddNatives(ent_Natives); + MF_AddNewNatives(ent_NewNatives); MF_AddNatives(engine_Natives); + MF_AddNewNatives(engine_NewNatives); MF_AddNatives(global_Natives); memset(glinfo.szLastLights, 0x0, 128); memset(glinfo.szRealLights, 0x0, 128); diff --git a/dlls/engine/amxxmodule.cpp b/dlls/engine/amxxmodule.cpp index d8c8c56c..ab2cbdb6 100755 --- a/dlls/engine/amxxmodule.cpp +++ b/dlls/engine/amxxmodule.cpp @@ -2437,6 +2437,7 @@ static amxx_module_info_s g_ModuleInfo = // Storage for the requested functions PFN_ADD_NATIVES g_fn_AddNatives; +PFN_ADD_NEW_NATIVES g_fn_AddNewNatives; PFN_BUILD_PATHNAME g_fn_BuildPathname; PFN_BUILD_PATHNAME_R g_fn_BuildPathnameR; PFN_GET_AMXADDR g_fn_GetAmxAddr; @@ -2513,6 +2514,9 @@ PFN_ADDLIBRARIES g_fn_AddLibraries; PFN_REMOVELIBRARIES g_fn_RemoveLibraries; PFN_OVERRIDENATIVES g_fn_OverrideNatives; PFN_GETLOCALINFO g_fn_GetLocalInfo; +PFN_AMX_REREGISTER g_fn_AmxReRegister; +PFN_REGISTERFUNCTIONEX g_fn_RegisterFunctionEx; +PFN_MESSAGE_BLOCK g_fn_MessageBlock; // *** Exports *** C_DLLEXPORT int AMXX_Query(int *interfaceVersion, amxx_module_info_s *moduleInfo) @@ -2563,6 +2567,7 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) REQFUNC("MergeDefinitionFile", g_fn_MergeDefinition_File, PFN_MERGEDEFINITION_FILE); REQFUNC("Format", g_fn_Format, PFN_FORMAT); REQFUNC("RegisterFunction", g_fn_RegisterFunction, PFN_REGISTERFUNCTION); + REQFUNC("RegisterFunctionEx", g_fn_RegisterFunctionEx, PFN_REGISTERFUNCTIONEX); // Amx scripts REQFUNC("GetAmxScript", g_fn_GetAmxScript, PFN_GET_AMXSCRIPT); @@ -2588,6 +2593,7 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) // Natives / Forwards REQFUNC("AddNatives", g_fn_AddNatives, PFN_ADD_NATIVES); + REQFUNC("AddNewNatives", g_fn_AddNewNatives, PFN_ADD_NEW_NATIVES); REQFUNC("RaiseAmxError", g_fn_RaiseAmxError, PFN_RAISE_AMXERROR); REQFUNC("RegisterForward", g_fn_RegisterForward, PFN_REGISTER_FORWARD); REQFUNC("RegisterSPForward", g_fn_RegisterSPForward, PFN_REGISTER_SPFORWARD); @@ -2627,11 +2633,15 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) REQFUNC("RegAuthFunc", g_fn_RegAuthFunc, PFN_REG_AUTH_FUNC); REQFUNC("UnregAuthFunc", g_fn_UnregAuthFunc, PFN_UNREG_AUTH_FUNC); + //Added in 1.75 REQFUNC("FindLibrary", g_fn_FindLibrary, PFN_FINDLIBRARY); REQFUNC("AddLibraries", g_fn_AddLibraries, PFN_ADDLIBRARIES); REQFUNC("RemoveLibraries", g_fn_RemoveLibraries, PFN_REMOVELIBRARIES); REQFUNC("OverrideNatives", g_fn_OverrideNatives, PFN_OVERRIDENATIVES); REQFUNC("GetLocalInfo", g_fn_GetLocalInfo, PFN_GETLOCALINFO); + REQFUNC("AmxReregister", g_fn_AmxReRegister, PFN_AMX_REREGISTER); + + REQFUNC("MessageBlock", g_fn_MessageBlock, PFN_MESSAGE_BLOCK); #ifdef MEMORY_TEST // Memory @@ -2766,6 +2776,7 @@ void ValidateMacros_DontCallThis_Smiley() MF_GetPlayerEdict(0); MF_Format("", 4, "str"); MF_RegisterFunction(NULL, ""); + MF_RegisterFunctionEx(NULL, ""); MF_SetPlayerTeamInfo(0, 0, ""); MF_PlayerPropAddr(0, 0); MF_RegAuthFunc(NULL); @@ -2773,7 +2784,8 @@ void ValidateMacros_DontCallThis_Smiley() MF_FindLibrary(NULL, LibType_Class); MF_AddLibraries(NULL, LibType_Class, NULL); MF_RemoveLibraries(NULL); - MF_OverrideNatives(NULL, ""); + MF_OverrideNatives(NULL, NULL); + MF_MessageBlock(0, 0, NULL); } #endif diff --git a/dlls/engine/amxxmodule.h b/dlls/engine/amxxmodule.h index 1136e594..964ad53b 100755 --- a/dlls/engine/amxxmodule.h +++ b/dlls/engine/amxxmodule.h @@ -2095,9 +2095,16 @@ enum LibType LibType_Class }; +#define MSGBLOCK_SET 0 +#define MSGBLOCK_GET 1 +#define BLOCK_NOT 0 +#define BLOCK_ONCE 1 +#define BLOCK_SET 2 + typedef void (*AUTHORIZEFUNC)(int player, const char *authstring); typedef int (*PFN_ADD_NATIVES) (const AMX_NATIVE_INFO * /*list*/); +typedef int (*PFN_ADD_NEW_NATIVES) (const AMX_NATIVE_INFO * /*list*/); typedef char * (*PFN_BUILD_PATHNAME) (const char * /*format*/, ...); typedef char * (*PFN_BUILD_PATHNAME_R) (char * /*buffer*/, size_t /* maxlen */, const char * /* format */, ...); typedef cell * (*PFN_GET_AMXADDR) (AMX * /*amx*/, cell /*offset*/); @@ -2183,8 +2190,10 @@ typedef void (*PFN_OVERRIDENATIVES) (AMX_NATIVE_INFO * /*natives*/, const ch typedef const char * (*PFN_GETLOCALINFO) (const char * /*name*/, const char * /*def*/); typedef int (*PFN_AMX_REREGISTER) (AMX * /*amx*/, AMX_NATIVE_INFO * /*list*/, int /*list*/); typedef void * (*PFN_REGISTERFUNCTIONEX) (void * /*pfn*/, const char * /*desc*/); +typedef void (*PFN_MESSAGE_BLOCK) (int /* mode */, int /* message */, int * /* opt */); extern PFN_ADD_NATIVES g_fn_AddNatives; +extern PFN_ADD_NEW_NATIVES g_fn_AddNewNatives; extern PFN_BUILD_PATHNAME g_fn_BuildPathname; extern PFN_BUILD_PATHNAME_R g_fn_BuildPathnameR; extern PFN_GET_AMXADDR g_fn_GetAmxAddr; @@ -2257,11 +2266,13 @@ extern PFN_OVERRIDENATIVES g_fn_OverrideNatives; extern PFN_GETLOCALINFO g_fn_GetLocalInfo; extern PFN_AMX_REREGISTER g_fn_AmxReRegister; extern PFN_REGISTERFUNCTIONEX g_fn_RegisterFunctionEx; +extern PFN_MESSAGE_BLOCK g_fn_MessageBlock; #ifdef MAY_NEVER_BE_DEFINED // Function prototypes for intellisense and similar systems // They understand #if 0 so we use #ifdef MAY_NEVER_BE_DEFINED int MF_AddNatives (const AMX_NATIVE_INFO *list) { } +int MF_AddNewNatives (const AMX_NATIVE_INFO *list) { } char * MF_BuildPathname (const char * format, ...) { } char * MF_BuildPathnameR (char *buffer, size_t maxlen, const char *fmt, ...) { } cell * MF_GetAmxAddr (AMX * amx, cell offset) { } @@ -2328,9 +2339,11 @@ void MF_OverrideNatives (AMX_NATIVE_INFO *natives, const char *myname) { } const char * MF_GetLocalInfo (const char *name, const char *def) { } int MF_AmxReRegister (AMX *amx, AMX_NATIVE_INFO *list, int number) { return 0; } void * MF_RegisterFunctionEx (void *pfn, const char *description) { } +void * MF_MessageBlock (int mode, int msg, int *opt) { } #endif // MAY_NEVER_BE_DEFINED #define MF_AddNatives g_fn_AddNatives +#define MF_AddNewNatives g_fn_AddNewNatives #define MF_BuildPathname g_fn_BuildPathname #define MF_BuildPathnameR g_fn_BuildPathnameR #define MF_FormatAmxString g_fn_FormatAmxString @@ -2404,6 +2417,7 @@ void MF_LogError(AMX *amx, int err, const char *fmt, ...); #define MF_GetLocalInfo g_fn_GetLocalInfo #define MF_AmxReRegister g_fn_AmxReRegister #define MF_RegisterFunctionEx g_fn_RegisterFunctionEx +#define MF_MessageBlock g_fn_MessageBlock #ifdef MEMORY_TEST /*** Memory ***/ diff --git a/dlls/engine/engine.cpp b/dlls/engine/engine.cpp index 199ed464..0e2fa601 100755 --- a/dlls/engine/engine.cpp +++ b/dlls/engine/engine.cpp @@ -1,4 +1,5 @@ #include "engine.h" +#include "amxmod_compat.h" struct usercmd_s *g_cmd; struct PlayerInfo plinfo[33]; @@ -97,11 +98,33 @@ static cell AMX_NATIVE_CALL halflife_time(AMX *amx, cell *params) return amx_ftoc(fVal); } -// RadiusDamage. Damages players within a certain radius. ToDo: add the -// damage messaging so players know where the damage is coming from -// (the red arrow-like things on the screen). -//(vexd) -static cell AMX_NATIVE_CALL RadiusDamage(AMX *amx, cell *params) { +//This is not exposed, and is only provided as a compatibility helper. +static cell AMX_NATIVE_CALL RadiusDamage_AMXMod(AMX *amx, cell *params) +{ + int ent = params[1]; + CHECK_ENTITY_SIMPLE(ent); + edict_t* pEntity = INDEXENT(ent); + float dmg = amx_ctof(params[2]); + cell *vInput = MF_GetAmxAddr(amx, params[3]); + float vOrig[3]; + + vOrig[0] = amx_ctof(vInput[0]); + vOrig[1] = amx_ctof(vInput[1]); + vOrig[2] = amx_ctof(vInput[2]); + + float rad = amx_ctof(params[4]); + int bit = params[5]; + int iLen; + char *vxWeapon = MF_GetAmxString(amx, params[6], 0, &iLen); + int hs = params[7]; + + RadiusDamage_AMXMod_Base(pEntity, dmg, vOrig, rad, bit, vxWeapon, hs); + + return 1; +} + +static cell AMX_NATIVE_CALL RadiusDamage_AMXModX(AMX *amx, cell *params) +{ cell *cAddr = MF_GetAmxAddr(amx,params[1]); REAL fCurrentX = amx_ctof(cAddr[0]); @@ -164,6 +187,24 @@ static cell AMX_NATIVE_CALL RadiusDamage(AMX *amx, cell *params) { return 1; } +// RadiusDamage. Damages players within a certain radius. ToDo: add the +// damage messaging so players know where the damage is coming from +// (the red arrow-like things on the screen). +//(vexd) +static cell AMX_NATIVE_CALL RadiusDamage(AMX *amx, cell *params) +{ + cell numParams = params[0] / sizeof(cell); + + if (numParams == 3) + { + return RadiusDamage_AMXModX(amx, params); + } else if (numParams == 7) { + return RadiusDamage_AMXMod(amx, params); + } + + return 0; +} + static cell AMX_NATIVE_CALL PointContents(AMX *amx, cell *params) { cell *cAddr = MF_GetAmxAddr(amx, params[1]); @@ -926,6 +967,12 @@ static cell AMX_NATIVE_CALL trace_forward(AMX *amx, cell *params) return 1; } +AMX_NATIVE_INFO engine_NewNatives[] = +{ + {"trace_line", trace_line}, + {NULL, NULL} +}; + AMX_NATIVE_INFO engine_Natives[] = { {"halflife_time", halflife_time}, @@ -934,7 +981,6 @@ AMX_NATIVE_INFO engine_Natives[] = { {"radius_damage", RadiusDamage}, {"point_contents", PointContents}, {"trace_normal", trace_normal}, - {"trace_line", trace_line}, {"trace_hull", trace_hull}, {"traceresult", traceresult}, @@ -965,6 +1011,6 @@ AMX_NATIVE_INFO engine_Natives[] = { {"is_visible", is_visible}, {"trace_forward", trace_forward}, - {NULL, NULL}, + {NULL, NULL} /////////////////// }; diff --git a/dlls/engine/engine.h b/dlls/engine/engine.h index 94a601b8..f2b3aa64 100755 --- a/dlls/engine/engine.h +++ b/dlls/engine/engine.h @@ -210,6 +210,7 @@ extern struct usercmd_s *g_cmd; extern struct PlayerInfo plinfo[33]; extern struct GlobalInfo glinfo; extern AMX_NATIVE_INFO engine_Natives[]; +extern AMX_NATIVE_INFO engine_NewNatives[]; extern CVector Impulses; extern CVector Thinks; extern CVector Touches; diff --git a/dlls/engine/engine.vcproj b/dlls/engine/engine.vcproj index 59d4be87..0e906593 100755 --- a/dlls/engine/engine.vcproj +++ b/dlls/engine/engine.vcproj @@ -117,6 +117,9 @@ Name="Source Files" Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + + @@ -137,6 +140,9 @@ Name="Header Files" Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + + diff --git a/dlls/engine/entity.cpp b/dlls/engine/entity.cpp index 9c1c6aa8..21103862 100755 --- a/dlls/engine/entity.cpp +++ b/dlls/engine/entity.cpp @@ -1509,6 +1509,12 @@ static cell AMX_NATIVE_CALL get_grenade_id(AMX *amx, cell *params) /* 4 param * return 0; } +AMX_NATIVE_INFO ent_NewNatives[] = +{ + {"DispatchKeyValue", DispatchKeyValue}, + {NULL, NULL} +}; + AMX_NATIVE_INFO ent_Natives[] = { {"create_entity", create_entity}, {"remove_entity", remove_entity}, @@ -1532,7 +1538,6 @@ AMX_NATIVE_INFO ent_Natives[] = { {"entity_set_origin", entity_set_origin}, {"entity_set_model", entity_set_model}, {"entity_set_size", entity_set_size}, - {"DispatchKeyValue", DispatchKeyValue}, {"DispatchSpawn", DispatchSpawn}, {"call_think", call_think}, @@ -1554,7 +1559,7 @@ AMX_NATIVE_INFO ent_Natives[] = { {"copy_keyvalue", copy_keyvalue}, - {NULL, NULL}, + {NULL, NULL} /////////////////// }; diff --git a/dlls/engine/entity.h b/dlls/engine/entity.h index 8d5c1097..cc7169a1 100755 --- a/dlls/engine/entity.h +++ b/dlls/engine/entity.h @@ -151,6 +151,7 @@ enum { void UTIL_SetSize(edict_t *pev, const Vector &vecMin, const Vector &vecMax); extern AMX_NATIVE_INFO ent_Natives[]; +extern AMX_NATIVE_INFO ent_NewNatives[]; #endif //_INCLUDE_ENGINE_ENTSTUFF diff --git a/plugins/include/Vexd_Utilities.inc b/plugins/include/Vexd_Utilities.inc deleted file mode 100755 index 24236589..00000000 --- a/plugins/include/Vexd_Utilities.inc +++ /dev/null @@ -1,104 +0,0 @@ -/* Vexd Utility backwards compatibility -* -* by the AMX Mod X Development Team -* -* This file is provided as is (no warranties). -*/ - -#if defined _Vexd_Utilities_included - #endinput -#endif -#define _Vexd_Utilities_included - -#include - -stock Entvars_Get_Int(iIndex, iVariable) - return entity_get_int(iIndex, iVariable) - -stock Entvars_Set_Int(iIndex, iVariable, iNewValue) - return entity_set_int(iIndex, iVariable, iNewValue) - -stock Float:Entvars_Get_Float(iIndex, iVariable) - return entity_get_float(iIndex, iVariable) - -stock Entvars_Set_Float(iIndex, iVariable, Float:fNewValue) - return entity_set_float(iIndex, iVariable, fNewValue) - -stock Entvars_Get_Vector(iIndex, iVariable, Float:vRetVector[3]) - return entity_get_vector(iIndex, iVariable, vRetVector) - -stock Entvars_Set_Vector(iIndex, iVariable, Float:vNewVector[3]) - return entity_set_vector(iIndex, iVariable, vNewVector) - -stock Entvars_Get_Edict(iIndex, iVariable) - return entity_get_edict(iIndex, iVariable) - -stock Entvars_Set_Edict(iIndex, iVariable, iNewIndex) - return entity_set_edict(iIndex, iVariable, iNewIndex) - -stock Entvars_Get_String(iIndex, iVariable, szReturnValue[], iReturnLen) - return entity_get_string(iIndex, iVariable, szReturnValue, iReturnLen) - -stock Entvars_Set_String(iIndex, iVariable, szNewValue[]) - return entity_set_string(iIndex, iVariable, szNewValue) - -stock Entvars_Get_Byte(iIndex, iVariable) - return entity_get_byte(iIndex, iVariable) - -stock Entvars_Set_Byte(iIndex, iVariable, iNewValue) - return entity_set_byte(iIndex, iVariable, iNewValue) - -stock CreateEntity(szClassname[]) - return create_entity(szClassname) - -stock ENT_SetModel(iIndex, szModel[]) - return entity_set_model(iIndex, szModel) - -stock ENT_SetOrigin(iIndex, Float:fNewOrigin[3]) - return entity_set_origin(iIndex, fNewOrigin) - -stock FindEntity(iIndex, szValue[]) - return find_ent_by_class(iIndex, szValue) - -stock RemoveEntity(iIndex) - return remove_entity(iIndex) - -stock TraceLn(iIgnoreEnt, Float:fStart[3], Float:fEnd[3], Float:vReturn[3]) - return trace_line(iIgnoreEnt, fStart, fEnd, vReturn) - -stock TraceNormal(iIgnoreEnt, Float:fStart[3], Float:fEnd[3], Float:vReturn[3]) - return trace_normal(iIgnoreEnt, fStart, fEnd, vReturn) - -stock VecToAngles(Float:fVector[3], Float:vReturn[3]) - return vector_to_angle(fVector, vReturn) - -stock Float:VecLength(Float:vVector[3]) - return vector_length(vVector) - -stock Float:VecDist(Float:vVector[3], Float:vVector2[3]) - return vector_distance(vVector, vVector2) - -stock MessageBlock(iMessage, iMessageFlags) - return set_msg_block(iMessage, iMessageFlags) - -stock GetMessageBlock(iMessage) - return get_msg_block(iMessage) - -stock Float:HLTime() - return halflife_time() - -stock FakeTouch(iToucher, iTouched) - return fake_touch(iToucher, iTouched) - -stock AttachView(iIndex, iTargetIndex) - return attach_view(iIndex, iTargetIndex) - -stock SetView(iIndex, ViewType) - return set_view(iIndex, ViewType) - -stock SetSpeak(iIndex, iSpeakFlags) - return set_speak(iIndex, iSpeakFlags) - -forward vexd_pfntouch(pToucher, pTouched) - -forward ServerFrame() \ No newline at end of file diff --git a/plugins/include/amxmisc.inc b/plugins/include/amxmisc.inc index f4d47d16..1f2e544b 100755 --- a/plugins/include/amxmisc.inc +++ b/plugins/include/amxmisc.inc @@ -11,6 +11,14 @@ #endif #define _amxmisc_included +#if defined AMXMOD_BCOMPAT +#if defined _translator_included +#define SIMPLE_T(%1) _T(%1) +#else +#define SIMPLE_T(%1) %1 +#endif +#endif + stock is_user_admin(id) { return ( get_user_flags(id)>0 && !(get_user_flags(id)&ADMIN_USER) ) @@ -30,13 +38,21 @@ stock cmd_access(id,level,cid,num) { } if ( has_access==0 ) { +#if defined AMXMOD_BCOMPAT + console_print(id, SIMPLE_T("You have no access to that command.")) +#else console_print(id,"%L",id,"NO_ACC_COM") +#endif return 0 } if (read_argc() < num) { new hcmd[32], hinfo[128], hflag get_concmd(cid,hcmd,31,hflag,hinfo,127,level) +#if defined AMXMOD_BCOMPAT + console_print(id, SIMPLE_T("Usage: %s %s"), hcmd, SIMPLE_T(hinfo)) +#else console_print(id,"%L: %s %s",id,"USAGE",hcmd,hinfo) +#endif return 0 } return 1 @@ -58,21 +74,33 @@ stock cmd_target(id,const arg[],flags = 1) { new player = find_player("bl",arg) if (player) { if ( player != find_player("blj",arg) ) { +#if defined AMXMOD_BCOMPAT + console_print(id, SIMPLE_T("There are more clients matching to your argument")) +#else console_print(id,"%L",id,"MORE_CL_MATCHT") +#endif return 0 } } else if ( ( player = find_player("c",arg) )==0 && arg[0]=='#' && arg[1] ) player = find_player("k",str_to_num(arg[1])) if (!player) { +#if defined AMXMOD_BCOMPAT + console_print(id, SIMPLE_T("Client with that name or userid not found")) +#else console_print(id,"%L",id,"CL_NOT_FOUND") +#endif return 0 } if (flags & 1) { if ((get_user_flags(player)&ADMIN_IMMUNITY) && ((flags&2)?(id!=player):true) ) { new imname[32] get_user_name(player,imname,31) +#if defined AMXMOD_BCOMPAT + console_print(id, SIMPLE_T("Client ^"%s^" has immunity"), imname) +#else console_print(id,"%L",id,"CLIENT_IMM",imname) +#endif return 0 } } @@ -80,7 +108,11 @@ stock cmd_target(id,const arg[],flags = 1) { if (!is_user_alive(player)) { new imname[32] get_user_name(player,imname,31) +#if defined AMXMOD_BCOMPAT + console_print(id, SIMPLE_T("That action can't be performed on dead client ^"%s^""), imname) +#else console_print(id,"%L",id,"CANT_PERF_DEAD",imname) +#endif return 0 } } @@ -88,7 +120,11 @@ stock cmd_target(id,const arg[],flags = 1) { if (is_user_bot(player)) { new imname[32] get_user_name(player,imname,31) +#if defined AMXMOD_BCOMPAT + console_print(id, SIMPLE_T("That action can't be performed on bot ^"%s^""), imname) +#else console_print(id,"%L",id,"CANT_PERF_BOT",imname) +#endif return 0 } } @@ -98,11 +134,20 @@ stock cmd_target(id,const arg[],flags = 1) { stock show_activity( id, const name[], {Float,_}: ... ) { new buffer[128] format_args( buffer , 127 , 2 ) - switch(get_cvar_num("amx_show_activity")) { - case 2: client_print(0,print_chat,"%L %s: %s", - id, is_user_admin(id) ? "ADMIN" : "PLAYER" , name , buffer ) - case 1: client_print(0,print_chat,"%L: %s", - id, is_user_admin(id) ? "ADMIN" : "PLAYER", buffer ) + switch(get_cvar_num("amx_show_activity")) + { + case 2: +#if defined AMXMOD_BCOMPAT + client_print(0, print_chat, "%s %s: %s", is_user_admin(id) ? SIMPLE_T("ADMIN") : SIMPLE_T("PLAYER"), name, buffer) +#else + client_print(0, print_chat, "%L %s: %s", id, is_user_admin(id) ? "ADMIN" : "PLAYER" , name , buffer ) +#endif + case 1: +#if defined AMXMOD_BCOMPAT + client_print(0, print_chat, "%s: %s", is_user_admin(id) ? SIMPLE_T("ADMIN") : SIMPLE_T("PLAYER"), buffer) +#else + client_print(0, print_chat, "%L: %s", id, is_user_admin(id) ? "ADMIN" : "PLAYER", buffer ) +#endif } } diff --git a/plugins/include/amxmod.inc b/plugins/include/amxmod.inc deleted file mode 100755 index d77894d7..00000000 --- a/plugins/include/amxmod.inc +++ /dev/null @@ -1,42 +0,0 @@ -/* AMX Mod X Backwards Compatibility -* -* by the AMX Mod X Development Team -* -* This file is provided as is (no warranties). -*/ - -#if defined _amxmod_included - #endinput -#endif -#define _amxmod_included - -#include -#include -#include -#include - -stock user_spawn(index) - return spawn(index) - -stock get_logfile( name[], len ) - return get_time("admin%m%d.log",name,len) - -stock get_user_money(index) - return cs_get_user_money(index) - -stock set_user_money(index,money,flash=1) - return cs_set_user_money(index,money,flash) - -stock numtostr(num,string[],len) - return num_to_str(num,string,len) - -stock strtonum(const string[]) - return str_to_num(string) - -stock build_path( path[] , len , {Float,_}:... ) -{ - new basedir[32] - get_localinfo("amxx_basedir",basedir,31) - format_args(path,len,2) - return replace(path,len,"$basedir",basedir) -} \ No newline at end of file diff --git a/plugins/include/engine.inc b/plugins/include/engine.inc index a0c570db..935c860e 100755 --- a/plugins/include/engine.inc +++ b/plugins/include/engine.inc @@ -121,7 +121,9 @@ native fake_touch(entTouched, entToucher); /* 2 formats. Format: DispatchKeyValue("KeyName","Value") - sets keyvalues for the entity specified in the keyvalue() forward. Format: DispatchKeyValue(index,"KeyName","Value") - Sets keyvalue for entity not specified in keyvalue() forward. */ +#if !defined AMXMOD_BCOMPAT native DispatchKeyValue(...); +#endif native get_keyvalue(entity, szKey[], value[], maxLength); @@ -131,14 +133,18 @@ native copy_keyvalue(szClassName[],sizea,szKeyName[],sizeb,szValue[],sizec); native DispatchSpawn(iIndex); /* Hurts/Kills players in a sphere, like an explosion, Multiplier determines damage. */ +#if !defined AMXMOD_BCOMPAT native radius_damage(Float:fExplodeAt[3], iDamageMultiplier, iRadiusMultiplier); +#endif /* Will return the contents of a point (inside map? in sky? outside map? etc.). */ native point_contents(Float:fCheckAt[3]); /* Trace a line from Start(X, Y, Z) to End(X, Y, Z), will return the point hit in vReturn[3] * and an entity index if an entity is hit. */ +#if !defined AMXMOD_BCOMPAT native trace_line(iIgnoreEnt, Float:fStart[3], Float:fEnd[3], Float:vReturn[3]); +#endif /* Traces a hull. */ native trace_hull(Float:origin[3],hull,ignoredent=0,ignoremonsters=0); diff --git a/plugins/include/float.inc b/plugins/include/float.inc index c158e4a6..ba037059 100755 --- a/plugins/include/float.inc +++ b/plugins/include/float.inc @@ -66,14 +66,22 @@ native Float:floatpower(Float:value, Float:exponent); native Float:floatlog(Float:value, Float:base=10.0); /* Return the sine, cosine or tangent. -* The input angle may be in radian, degrees or grades. */ + * The input angle may be in radians, degrees or grades. */ native Float:floatsin(Float:value, anglemode:mode=radian); native Float:floatcos(Float:value, anglemode:mode=radian); native Float:floattan(Float:value, anglemode:mode=radian); +/* Return the hyperbolic sine, cosine or tangent. + * The input angle may be in radians, degrees or grades. */ +native Float:floatsinh(Float:angle, anglemode:mode=radian); +native Float:floatcosh(Float:angle, anglemode:mode=radian); +native Float:floattanh(Float:angle, anglemode:mode=radian); + /* Return the absolute value */ native Float:floatabs(Float:value); +/* Return the angle of a sine, cosine or tangent. + * The output angle may be in radians, degrees, or grades. */ native Float:floatatan(Float:angle, radix); native Float:floatacos(Float:angle, radix); native Float:floatasin(Float:angle, radix); diff --git a/plugins/include/hlsdk_const.inc b/plugins/include/hlsdk_const.inc index dcba23d7..112773a8 100644 --- a/plugins/include/hlsdk_const.inc +++ b/plugins/include/hlsdk_const.inc @@ -159,6 +159,12 @@ #define DMG_MORTAR (1<<23) // Hit by air raid (done to distinguish grenade from mortar) #define DMG_TIMEBASED (~(0x3fff)) // Mask for time-based damage +// The fNoMonsters parameter of EngFunc_TraceLine, EngFunc_TraceMonsterHull, EngFunc_TraceHull, and EngFunc_TraceSphere +#define DONT_IGNORE_MONSTERS 0 +#define IGNORE_MONSTERS 1 +#define IGNORE_MISSILE 2 +#define IGNORE_GLASS 0x100 + // The hullnumber paramater of EngFunc_TraceHull, EngFunc_TraceModel and DLLFunc_GetHullBounds #define HULL_POINT 0 #define HULL_HUMAN 1 diff --git a/plugins/include/xtrafun.inc b/plugins/include/xtrafun.inc deleted file mode 100755 index 0342b75f..00000000 --- a/plugins/include/xtrafun.inc +++ /dev/null @@ -1,95 +0,0 @@ -/* Xtrafun backwards compatibility -* -* by the AMX Mod X Development Team -* These natives were originally made by SpaceDude, EJ, and JustinHoMi. -* -* This file is provided as is (no warranties). -*/ - -#if !defined _xtrafun_included - #define _xtrafun_included - -#if !defined _engine_included - #include -#endif - -/* Gets the velocity of an entity */ -stock get_entity_velocity(index, velocity[3]) { - new Float:vector[3] - entity_get_vector(index, EV_VEC_velocity, vector) - FVecIVec(vector, velocity) -} - -/* Sets the velocity of an entity */ -stock set_entity_velocity(index, velocity[3]) { - new Float:vector[3] - IVecFVec(velocity, vector) - entity_set_vector(index, EV_VEC_velocity, vector) -} - -/* Gets the origin of an entity */ -stock get_entity_origin(index, origin[3]) { - new Float:vector[3] - entity_get_vector(index, EV_VEC_origin, vector) - FVecIVec(vector, origin) -} - -/* Sets the origin of an entity */ -stock set_entity_origin(index, origin[3]) { - new Float:vector[3] - IVecFVec(origin, vector) - entity_set_vector(index, EV_VEC_origin, vector) -} - -/* Get the index of the grenade belonging to index. - * Model of grenade is returned in model[]. - * Specify the grenadeindex to start searching from, - * or leave it at 0 to search from the start. - * Returns grenade index. - * Paths + models of grenades in Counter-Strike: - * HEGRENADE = "models/w_hegrenade.mdl" - * FLASHBANG = "models/w_flashbang.mdl" - * SMOKEGRENADE = "models/w_smokegrenade.mdl" */ -stock get_grenade_index(index, model[], len, grenadeindex = 0) { - new entfind = grenadeindex - new entowner = index - - for (;;) { - entfind = find_ent_by_class(entfind, "grenade") - - if (entfind && is_valid_ent(entfind)) { - if (entity_get_edict(entFind, EV_ENT_owner) == entowner) { - entity_get_string(entfind, EV_SZ_model, model) - return entfind - } - } - else { - // Eventually comes here if loop fails to find a grenade with specified owner. - return 0; - } - } -} - -/* Find the number of entities in the game */ -stock current_num_ents() { - return entity_count(); -} - -enum { - classname = 0, - target, - targetname -} - -/* Find an entity ID from start_from_ent id (use 0 to start from - * the beginning, category is either "classname", "target" or - * "targetname", value is the name you are searching for */ -stock find_entity(start_from_ent, category, value[]) { - switch (category) { - case target: return find_ent_by_target(start_from_ent, value) - case targetname: return find_ent_by_tname(start_from_ent, value) - } - return find_ent_by_class(start_from_ent, value) -} - -#endif // _xtrafun_included \ No newline at end of file