mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
438 lines
16 KiB
C++
438 lines
16 KiB
C++
// ------------------------------------------------------------------------------------------------
|
|
#include "Misc/Weapon.hpp"
|
|
#include "Core/Utility.hpp"
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#include <algorithm>
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
namespace SqMod {
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
static String CS_Weapon_Names[] = { // NOLINT(cert-err58-cpp)
|
|
/* 0 */ "Unarmed", /* 1 */ "Brass Knuckles",
|
|
/* 2 */ "Screwdriver", /* 3 */ "Golf Club",
|
|
/* 4 */ "Nightstick", /* 5 */ "Knife",
|
|
/* 6 */ "Baseball Bat", /* 7 */ "Hammer",
|
|
/* 8 */ "Meat Cleaver", /* 9 */ "Machete",
|
|
/* 10 */ "Katana", /* 11 */ "Chainsaw",
|
|
/* 12 */ "Grenade", /* 13 */ "Remote Detonation Grenade",
|
|
/* 14 */ "Tear Gas", /* 15 */ "Molotov Cocktails",
|
|
/* 16 */ "Missile", /* 17 */ "Colt .45",
|
|
/* 18 */ "Python", /* 19 */ "Pump-Action Shotgun",
|
|
/* 20 */ "SPAS-12 Shotgun", /* 21 */ "Stubby Shotgun",
|
|
/* 22 */ "TEC-9", /* 23 */ "Uzi",
|
|
/* 24 */ "Silenced Ingram", /* 25 */ "MP5",
|
|
/* 26 */ "M4", /* 27 */ "Ruger",
|
|
/* 28 */ "Sniper Rifle", /* 29 */ "Laserscope Sniper Rifle",
|
|
/* 30 */ "Rocket Launcher", /* 31 */ "Flamethrower",
|
|
/* 32 */ "M60", /* 33 */ "Minigun",
|
|
/* 34 */ "Bomb", /* 35 */ "Helicanon",
|
|
/* 36 */ "Camera", /* 37 */ "",
|
|
/* 38 */ "", /* 39 */ "Vehicle",
|
|
/* 40 */ "Heliblade", /* 41 */ "Explosion",
|
|
/* 42 */ "Driveby", /* 43 */ "Drowned",
|
|
/* 44 */ "Fall", /* 45 */ "",
|
|
/* 46 */ "", /* 47 */ "",
|
|
/* 48 */ "", /* 49 */ "",
|
|
/* 50 */ "", /* 51 */ "Explosion",
|
|
/* 52 */ "", /* 53 */ "",
|
|
/* 54 */ "", /* 55 */ "",
|
|
/* 56 */ "", /* 57 */ "",
|
|
/* 58 */ "", /* 59 */ "",
|
|
/* 60 */ "Heliblade", /* 61 */ "",
|
|
/* 62 */ "", /* 63 */ "",
|
|
/* 64 */ "", /* 65 */ "",
|
|
/* 66 */ "", /* 67 */ "",
|
|
/* 68 */ "", /* 69 */ "",
|
|
/* 70 */ "Suicide", /* 71 */ ""
|
|
};
|
|
/// Fall back for custom weapon names.
|
|
static std::unordered_map<uint32_t, String> CS_Custom_Weapon_Names{};
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
static inline bool IsCustomWeapon(uint32_t id)
|
|
{
|
|
return (id > 70);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
uint32_t GetWeaponSlot(uint32_t id)
|
|
{
|
|
switch(id) {
|
|
case 0:
|
|
case 1:
|
|
return 0;
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
return 1;
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
case 15:
|
|
return 2;
|
|
case 17:
|
|
case 18:
|
|
return 3;
|
|
case 19:
|
|
case 20:
|
|
case 21:
|
|
return 4;
|
|
case 22:
|
|
case 23:
|
|
case 24:
|
|
case 25:
|
|
return 5;
|
|
case 26:
|
|
case 27:
|
|
return 6;
|
|
case 28:
|
|
case 29:
|
|
return 8;
|
|
case 30:
|
|
case 31:
|
|
case 32:
|
|
case 33:
|
|
return 7;
|
|
default:
|
|
return 255;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
const char * GetWeaponName(uint32_t id)
|
|
{
|
|
// Can we consider this a custom weapon ID?
|
|
if (IsCustomWeapon(id))
|
|
{
|
|
// Attempt to look for the specified identifier
|
|
auto it = CS_Custom_Weapon_Names.find(id);
|
|
// If we found anything than return the associated name
|
|
if ((it != CS_Custom_Weapon_Names.end()))
|
|
{
|
|
return it->second.c_str();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return CS_Weapon_Names[id].c_str(); // Use the standard weapon name
|
|
}
|
|
// Fall back to an empty name
|
|
return _SC("");
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void SetWeaponName(uint32_t id, StackStrF & name)
|
|
{
|
|
// Can we consider this a custom weapon ID?
|
|
if (IsCustomWeapon(id))
|
|
{
|
|
// Attempt to insert or update the name into the custom weapon table
|
|
CS_Custom_Weapon_Names[id] = String(name.mPtr, static_cast< size_t >(name.mLen));
|
|
}
|
|
else
|
|
{
|
|
// Attempt to insert or update the name into the standard weapon table
|
|
CS_Weapon_Names[id].assign(name.mPtr);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
uint32_t GetCustomWeaponNamePoolSize()
|
|
{
|
|
return static_cast< uint32_t >(CS_Custom_Weapon_Names.size());
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
void ClearCustomWeaponNamePool()
|
|
{
|
|
CS_Custom_Weapon_Names.clear();
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int32_t GetWeaponID(StackStrF & name)
|
|
{
|
|
// Clone the string into an editable version
|
|
String str(name.mPtr, static_cast< size_t >(name.mLen));
|
|
// Strip non-alphanumeric characters from the name
|
|
str.erase(std::remove_if(str.begin(), str.end(), [](char c) -> bool { return std::isalnum(c) == 0; }), str.end());
|
|
// Convert the string to lowercase
|
|
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
|
// See if we still have a valid name after the cleanup
|
|
if(str.length() < 1)
|
|
{
|
|
return SQMOD_UNKNOWN;
|
|
}
|
|
// Grab the actual length of the string
|
|
const uint32_t len = ConvTo< uint32_t >::From(str.length());
|
|
// Get the most significant characters used to identify a weapon
|
|
CharT a = str[0], b = 0, c = 0, d = str[len-1];
|
|
// Look for deeper specifiers
|
|
if(len > 2)
|
|
{
|
|
c = str[2];
|
|
b = str[1];
|
|
}
|
|
else if(len > 1)
|
|
{
|
|
b = str[1];
|
|
}
|
|
// Search for a pattern in the name
|
|
switch(a)
|
|
{
|
|
// [B]aseball Bat
|
|
// [B]omb
|
|
// [B]rass Knuckles
|
|
case 'b':
|
|
// [Ba]seball Bat
|
|
if (b == 'a') return SQMOD_WEAPON_BASEBALLBAT;
|
|
// [Bo]mb
|
|
else if (b == 'o') return SQMOD_WEAPON_BOMB;
|
|
// [Br]ass Knuckles
|
|
else if (b == 'r') return SQMOD_WEAPON_BRASSKNUCKLES;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [C]amera
|
|
// [C]hainsaw
|
|
// [C]olt .45
|
|
case 'c':
|
|
// [Ca]mera
|
|
if (b == 'a') return SQMOD_WEAPON_CAMERA;
|
|
// [Ch]ainsaw
|
|
else if (b == 'h') return SQMOD_WEAPON_CHAINSAW;
|
|
// [Co]lt .45
|
|
else if (b == 'o') return SQMOD_WEAPON_COLT45;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [D]riveby
|
|
// [D]rowned
|
|
case 'd':
|
|
// [Dr]iveby
|
|
if (b == 'r' && (c == 'i' || d == 'y')) return SQMOD_WEAPON_DRIVEBY;
|
|
// [Dr]owned
|
|
else if (b == 'r' && (c == 'o' || d == 'd')) return SQMOD_WEAPON_DROWNED;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [E]xplosion
|
|
case 'e': return SQMOD_WEAPON_EXPLOSION2;
|
|
// [F]all
|
|
// [F]lamethrower
|
|
case 'f':
|
|
// [Fa]ll
|
|
if (b == 'a') return SQMOD_WEAPON_FALL;
|
|
// [Fl]amethrower
|
|
else if (b == 'l') return SQMOD_WEAPON_FLAMETHROWER;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [G]olf Club
|
|
// [G]renade
|
|
case 'g':
|
|
// [Go]lf Club
|
|
if (b == 'o') return SQMOD_WEAPON_GOLFCLUB;
|
|
// [Gr]enade
|
|
else if (b == 'r') return SQMOD_WEAPON_GRENADE;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [H]ammer
|
|
// [H]eliblades1/A
|
|
// [H]eliblades2/B
|
|
// [H]elicannon
|
|
case 'h':
|
|
// [Ha]mmer
|
|
if (b == 'a') return SQMOD_WEAPON_HAMMER;
|
|
// [He]li[b]lades[1/A]
|
|
else if (b == 'e' && (c == 'b' || (len > 4 && str[4] == 'b')) && (d == '1' || d == 'a')) return SQMOD_WEAPON_HELIBLADES1;
|
|
// [He]li[b]lades[2/B]
|
|
else if (b == 'e' && (c == 'b' || (len > 4 && str[4] == 'b')) && (d == '2' || d == 'b')) return SQMOD_WEAPON_HELIBLADES2;
|
|
// [He]li[c]anno[n]
|
|
else if (b == 'e' && (d == 'c' || d == 'n' || (len > 4 && str[4] == 'c'))) return SQMOD_WEAPON_HELICANNON;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [K]atana
|
|
// [K]nife
|
|
case 'k':
|
|
// [Ka]tana
|
|
if (b == 'a') return SQMOD_WEAPON_KATANA;
|
|
// [Kn]ife
|
|
else if (b == 'n') return SQMOD_WEAPON_KNIFE;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [L]aserscope Sniper Rifle
|
|
case 'l': return SQMOD_WEAPON_LASERSCOPE;
|
|
// [M]4
|
|
// [M]60
|
|
// [M]achete
|
|
// [M]eat Cleaver
|
|
// [M]inigun
|
|
// [M]issile
|
|
// [M]olotov Cocktails
|
|
// [M]P5
|
|
case 'm':
|
|
// [M4]
|
|
if (b == '4') return SQMOD_WEAPON_M4;
|
|
// [M6]0
|
|
else if (b == '6') return SQMOD_WEAPON_M60;
|
|
// [Ma]chete
|
|
else if (b == 'a') return SQMOD_WEAPON_MACHETE;
|
|
// [Me]at Cleaver
|
|
else if (b == 'e') return SQMOD_WEAPON_MEATCLEAVER;
|
|
// [Min]igu[n]
|
|
else if (b == 'i' && (c == 'n' || d == 'n')) return SQMOD_WEAPON_MINIGUN;
|
|
// [Mis]sil[e]
|
|
else if (b == 'i' && (c == 's' || d == 's' || d == 'e')) return SQMOD_WEAPON_ROCKET;
|
|
// [Mo]lotov Cocktails
|
|
else if (b == 'o') return SQMOD_WEAPON_MOLOTOV;
|
|
// [MP]5
|
|
else if (b == 'p') return SQMOD_WEAPON_MP5;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [N]ightstick
|
|
case 'n': return SQMOD_WEAPON_NIGHTSTICK;
|
|
case 'i': return SQMOD_WEAPON_INGRAM;
|
|
// [P]ump-Action Shotgun
|
|
// [P]ython
|
|
case 'p':
|
|
// [Pu]mp-Action Shotgun
|
|
if (b == 'u') return SQMOD_WEAPON_SHOTGUN;
|
|
// [Py]thon
|
|
else if (b == 'y') return SQMOD_WEAPON_PYTHON;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [R]emote Detonation Grenade
|
|
// [R]ocket Launcher
|
|
// [R]uger
|
|
case 'r':
|
|
// [Re]mote Detonation Grenade
|
|
if (b == 'e') return SQMOD_WEAPON_REMOTE;
|
|
// [Ro]cket Launcher
|
|
else if (b == 'o') return SQMOD_WEAPON_ROCKETLAUNCHER;
|
|
// [Ru]ger
|
|
else if (b == 'u') return SQMOD_WEAPON_RUGER;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [S]crewdriver
|
|
// [S]ilenced Ingram
|
|
// [S]niper Rifle
|
|
// [S]PAS-12 Shotgun
|
|
// [S]tubby Shotgun
|
|
// [S]uicide
|
|
// Pump action [S]hotgun
|
|
case 's':
|
|
// [Sc]rewdriver
|
|
if (b == 'c') return SQMOD_WEAPON_SCREWDRIVER;
|
|
// [Si]lenced Ingram
|
|
else if (b == 'i') return SQMOD_WEAPON_INGRAM;
|
|
// [Sn]iper Rifle
|
|
else if (b == 'n') return SQMOD_WEAPON_SNIPER;
|
|
// [SP]AS-12 Shotgun
|
|
else if (b == 'p') return SQMOD_WEAPON_SPAS12;
|
|
// [St]ubby Shotgun
|
|
else if (b == 't') return SQMOD_WEAPON_STUBBY;
|
|
// [Su]icide
|
|
else if (b == 'u') return SQMOD_WEAPON_SUICIDE;
|
|
// Pump action [Sh]otgun
|
|
else if (b == 'h') return SQMOD_WEAPON_SHOTGUN;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [T]ear Gas
|
|
// [T]EC-9
|
|
case 't':
|
|
// [Tea]r Ga[s]
|
|
if (b == 'e' && (c == 'a' || d == 's')) return SQMOD_WEAPON_TEARGAS;
|
|
// [TEC]-[9]
|
|
else if (b == 'e' && (c == 'c' || d == '9')) return SQMOD_WEAPON_TEC9;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [U]narmed
|
|
// [U]zi
|
|
case 'u':
|
|
// [Un]armed
|
|
if (b == 'n') return SQMOD_WEAPON_UNARMED;
|
|
// [Uz]i
|
|
else if (b == 'z') return SQMOD_WEAPON_UZI;
|
|
// Default to unknwon
|
|
else return SQMOD_UNKNOWN;
|
|
// [V]ehicle
|
|
case 'v': return SQMOD_WEAPON_VEHICLE;
|
|
// Default to unknwon
|
|
default: return SQMOD_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool IsWeaponValid(int32_t id)
|
|
{
|
|
const SQChar * name = GetWeaponName(static_cast< uint32_t >(id));
|
|
return (name && *name != '\0');
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
int32_t WeaponToModel(int32_t id)
|
|
{
|
|
switch (id)
|
|
{
|
|
case SQMOD_WEAPON_UNARMED: return 293;
|
|
case SQMOD_WEAPON_BRASSKNUCKLES: return 259;
|
|
case SQMOD_WEAPON_SCREWDRIVER: return 260;
|
|
case SQMOD_WEAPON_GOLFCLUB: return 261;
|
|
case SQMOD_WEAPON_NIGHTSTICK: return 262;
|
|
case SQMOD_WEAPON_KNIFE: return 263;
|
|
case SQMOD_WEAPON_BASEBALLBAT: return 264;
|
|
case SQMOD_WEAPON_HAMMER: return 265;
|
|
case SQMOD_WEAPON_MEATCLEAVER: return 266;
|
|
case SQMOD_WEAPON_MACHETE: return 267;
|
|
case SQMOD_WEAPON_KATANA: return 268;
|
|
case SQMOD_WEAPON_CHAINSAW: return 269;
|
|
case SQMOD_WEAPON_GRENADE: return 270;
|
|
case SQMOD_WEAPON_REMOTE: return 291;
|
|
case SQMOD_WEAPON_TEARGAS: return 271;
|
|
case SQMOD_WEAPON_MOLOTOV: return 272;
|
|
case SQMOD_WEAPON_ROCKET: return 273;
|
|
case SQMOD_WEAPON_COLT45: return 274;
|
|
case SQMOD_WEAPON_PYTHON: return 275;
|
|
case SQMOD_WEAPON_SHOTGUN: return 277;
|
|
case SQMOD_WEAPON_SPAS12: return 278;
|
|
case SQMOD_WEAPON_STUBBY: return 279;
|
|
case SQMOD_WEAPON_TEC9: return 281;
|
|
case SQMOD_WEAPON_UZI: return 282;
|
|
case SQMOD_WEAPON_INGRAM: return 283;
|
|
case SQMOD_WEAPON_MP5: return 284;
|
|
case SQMOD_WEAPON_M4: return 280;
|
|
case SQMOD_WEAPON_RUGER: return 276;
|
|
case SQMOD_WEAPON_SNIPER: return 285;
|
|
case SQMOD_WEAPON_LASERSCOPE: return 286;
|
|
case SQMOD_WEAPON_ROCKETLAUNCHER: return 287;
|
|
case SQMOD_WEAPON_FLAMETHROWER: return 288;
|
|
case SQMOD_WEAPON_M60: return 289;
|
|
case SQMOD_WEAPON_MINIGUN: return 290;
|
|
case SQMOD_WEAPON_HELICANNON: return 294;
|
|
case SQMOD_WEAPON_CAMERA: return 292;
|
|
default: return SQMOD_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
bool IsWeaponNatural(int32_t id)
|
|
{
|
|
switch (id)
|
|
{
|
|
case SQMOD_WEAPON_VEHICLE:
|
|
case SQMOD_WEAPON_DRIVEBY:
|
|
case SQMOD_WEAPON_DROWNED:
|
|
case SQMOD_WEAPON_FALL:
|
|
case SQMOD_WEAPON_EXPLOSION2:
|
|
case SQMOD_WEAPON_SUICIDE: return true;
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
} // Namespace:: SqMod
|