Add a spell forcer and fix a bunch of issues
- Crithack + nospread compatibility fixes - Automelee hitting air - Nospread ghost crash
This commit is contained in:
parent
6463ff25da
commit
9132b8470e
@ -8,5 +8,6 @@
|
||||
<Include path="nullifiedcat/misc/autoparty.xml"/>
|
||||
<Include path="nullifiedcat/misc/autoload.xml"/>
|
||||
<Include path="nullifiedcat/misc/datacenters.xml"/>
|
||||
<Include path="nullifiedcat/misc/spellforcer.xml"/>
|
||||
</TabContainer>
|
||||
</Tab>
|
||||
|
114
data/menu/nullifiedcat/misc/spellforcer.xml
Normal file
114
data/menu/nullifiedcat/misc/spellforcer.xml
Normal file
@ -0,0 +1,114 @@
|
||||
<Tab name="Spellforcer" padding="4 4 4 4">
|
||||
<Box height="content" width="content" padding="12 6 6 6" name="Spellforcer">
|
||||
<List width="250">
|
||||
<AutoVariable width="fill" target="spellforce.enabled" label="Enable Spell forcer" tooltip="Attempts to force a specific spell for yourself, and a different one and onto enemies."/>
|
||||
<LabeledObject width="fill" label="Default spell">
|
||||
<Select target="spellforce.default_spell">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Fireball" value="0"/>
|
||||
<Option name="Bats" value="1"/>
|
||||
<Option name="Uber" value="2"/>
|
||||
<Option name="Pumpkin Bombs" value="3"/>
|
||||
<Option name="Jump" value="4"/>
|
||||
<Option name="Invisibility" value="5"/>
|
||||
<Option name="Lighting Storm" value="7"/>
|
||||
<Option name="Minify" value="8"/>
|
||||
<Option name="Meteor" value="9"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Default Rare spell">
|
||||
<Select target="spellforce.default_spell.rare">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Lighting Storm" value="7"/>
|
||||
<Option name="Minify" value="8"/>
|
||||
<Option name="Meteor" value="9"/>
|
||||
<Option name="Monoculus" value="10"/>
|
||||
<Option name="Skeleton Army" value="11"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Default enemy spell" tooltip="Left side is the normal spell pickup, right side is the rare spell pickup.">
|
||||
<Select target="spellforce.default_spell.enemies">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Fireball/Meteors" value="0"/>
|
||||
<Option name="Bats/Skeleton Army" value="1"/>
|
||||
<Option name="Uber/Meteors" value="2"/>
|
||||
<Option name="Pumpkin Bombs/Lightning Storm" value="3"/>
|
||||
<Option name="Jump/Lightning Storm" value="4"/>
|
||||
<Option name="Invisibility/Lightning Storm" value="5"/>
|
||||
<Option name="Lighting Storm/Minify" value="7"/>
|
||||
<Option name="Minify/Minify" value="8"/>
|
||||
<Option name="Meteor/Meteor" value="9"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Helltower spell">
|
||||
<Select target="spellforce.helltower_spell">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Fireball" value="0"/>
|
||||
<Option name="Bats" value="1"/>
|
||||
<Option name="Uber" value="2"/>
|
||||
<Option name="Pumpkin Bombs" value="3"/>
|
||||
<Option name="Jump" value="4"/>
|
||||
<Option name="Invisibility" value="5"/>
|
||||
<Option name="Teleport" value="6"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Helltower enemy spell" tooltip="Left side is the normal spell pickup, right side is the rare spell pickup.">
|
||||
<Select target="spellforce.helltower_spell.enemies">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Fireball/Skeletons" value="0"/>
|
||||
<Option name="Bats/Skeletons" value="1"/>
|
||||
<Option name="Uber/Monoculus" value="2"/>
|
||||
<Option name="Pumpkin Bombs/Monoculus" value="3"/>
|
||||
<Option name="Jump/Lightning Storm" value="4"/>
|
||||
<Option name="Invisibility/Minify" value="5"/>
|
||||
<Option name="Teleport/Monoculus" value="6"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Carnival of Carnage spell">
|
||||
<Select target="spellforce.doomsday_spell">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Fireball" value="0"/>
|
||||
<Option name="Uber" value="2"/>
|
||||
<Option name="Jump" value="4"/>
|
||||
<Option name="Invisibility" value="5"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Carnival of Carnage Rare spell">
|
||||
<Select target="spellforce.doomsday_spell.rare">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Lighting Storm" value="7"/>
|
||||
<Option name="Minify" value="8"/>
|
||||
<Option name="Meteor" value="9"/>
|
||||
<Option name="Monoculus" value="10"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Carnival of Carnage enemy spell" tooltip="Left side is the normal spell pickup, right side is the rare spell pickup.">
|
||||
<Select target="spellforce.doomsday_spell.enemies">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Fireball/Meteor" value="0"/>
|
||||
<Option name="Uber/Meteor" value="2"/>
|
||||
<Option name="Jump/Monoculus" value="4"/>
|
||||
<Option name="Invisibility/Minify" value="5"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Bumper Kart Spell">
|
||||
<Select target="spellforce.bumper_spell">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Boxing Rocket" value="12"/>
|
||||
<Option name="B.A.S.E. Jump" value="13"/>
|
||||
<Option name="Overheal" value="14"/>
|
||||
<Option name="Bomb Head" value="15"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
<LabeledObject width="fill" label="Bumper Kart Enemy Spell">
|
||||
<Select target="spellforce.bumper_spell.enemies">
|
||||
<Option name="Disabled" value="-1"/>
|
||||
<Option name="Boxing Rocket" value="12"/>
|
||||
<Option name="B.A.S.E. Jump" value="13"/>
|
||||
<Option name="Overheal" value="14"/>
|
||||
<Option name="Bomb Head" value="15"/>
|
||||
</Select>
|
||||
</LabeledObject>
|
||||
</List>
|
||||
</Box>
|
||||
</Tab>
|
@ -171,6 +171,7 @@ public:
|
||||
offset_t res_iTeam;
|
||||
offset_t res_iScore;
|
||||
offset_t res_bAlive;
|
||||
offset_t res_bValid;
|
||||
offset_t m_nChargeResistType;
|
||||
offset_t m_hHealingTarget;
|
||||
offset_t m_flChargeLevel; // Medigun
|
||||
|
@ -29,6 +29,7 @@ public:
|
||||
int getClass(int idx);
|
||||
int getTeam(int idx);
|
||||
bool isAlive(int idx);
|
||||
bool isValid(int idx);
|
||||
|
||||
int entity;
|
||||
};
|
||||
|
@ -15,4 +15,21 @@ public:
|
||||
int winning_team; // 56 | 4 bytes | 60
|
||||
char pad2[974]; // 60 | 974 bytes | 1034
|
||||
bool isPVEMode; // 1034 | 1 byte | 1035
|
||||
};
|
||||
char pad3[15]; // 1035 | 15 bytes | 1050
|
||||
int isUsingSpells; // 1050 | 4 bytes | 1054
|
||||
char pad4[790]; // 1054 | 790 bytes | 1844
|
||||
int halloweenScenario; // 1844 | 4 bytes | 1848
|
||||
|
||||
bool isUsingSpells_fn()
|
||||
{
|
||||
auto tf_spells_enabled = g_ICvar->FindVar("tf_spells_enabled");
|
||||
if (tf_spells_enabled->GetBool())
|
||||
return true;
|
||||
|
||||
// Hightower
|
||||
if (halloweenScenario == 4)
|
||||
return true;
|
||||
|
||||
return isUsingSpells;
|
||||
}
|
||||
} __attribute__((packed));
|
||||
|
@ -39,6 +39,7 @@ void NetVars::Init()
|
||||
this->m_flMaxspeed = gNetvars.get_offset("DT_BasePlayer", "m_flMaxspeed");
|
||||
res_iTeam = gNetvars.get_offset("DT_TFPlayerResource", "baseclass", "m_iTeam");
|
||||
res_bAlive = gNetvars.get_offset("DT_TFPlayerResource", "baseclass", "m_bAlive");
|
||||
res_bValid = gNetvars.get_offset("DT_TFPlayerResource", "baseclass", "m_bValid");
|
||||
this->res_iMaxBuffedHealth = gNetvars.get_offset("DT_TFPlayerResource", "m_iMaxBuffedHealth");
|
||||
m_angEyeAngles = gNetvars.get_offset("DT_TFPlayer", "tfnonlocaldata", "m_angEyeAngles[0]");
|
||||
m_angEyeAnglesLocal = gNetvars.get_offset("DT_TFPlayer", "tflocaldata", "m_angEyeAngles[0]");
|
||||
|
@ -1160,7 +1160,7 @@ static CatCommand debug_print_crit_info("debug_print_crit_info", "Print a bunch
|
||||
static InitRoutine init(
|
||||
[]()
|
||||
{
|
||||
EC::Register(EC::CreateMoveLate, CreateMove, "crit_cm");
|
||||
EC::Register(EC::CreateMoveLate, CreateMove, "crit_cm", EC::late);
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(EC::Draw, Draw, "crit_draw");
|
||||
#endif
|
||||
|
@ -37,6 +37,7 @@ set(files "${CMAKE_CURRENT_LIST_DIR}/AutoJoin.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Noisemaker.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/PureBypass.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Trigger.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/SpellForcer.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/UberSpam.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Walkbot.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Warp.cpp")
|
||||
|
@ -958,8 +958,6 @@ static InitRoutine init_pyrovision(
|
||||
{
|
||||
if (HasCondition<TFCond_HalloweenKartNoTurn>(LOCAL_E))
|
||||
RemoveCondition<TFCond_HalloweenKartNoTurn>(LOCAL_E);
|
||||
if (HasCondition<TFCond_FreezeInput>(LOCAL_E))
|
||||
RemoveCondition<TFCond_FreezeInput>(LOCAL_E);
|
||||
}
|
||||
},
|
||||
"remove_cart_cond");
|
||||
|
@ -266,7 +266,7 @@ static std::pair<CachedEntity *, float> getNearestPlayerDistance()
|
||||
for (int i = 1; i <= g_IEngine->GetMaxClients(); i++)
|
||||
{
|
||||
CachedEntity *ent = ENTITY(i);
|
||||
if (CE_VALID(ent) && ent->m_vecDormantOrigin() && ent->m_bAlivePlayer() && ent->m_bEnemy() && g_pLocalPlayer->v_Origin.DistTo(ent->m_vecOrigin()) < distance && player_tools::shouldTarget(ent) && !IsPlayerInvisible(ent))
|
||||
if (CE_VALID(ent) && ent->m_vecDormantOrigin() && g_pPlayerResource->isAlive(ent->m_IDX) && ent->m_bEnemy() && g_pLocalPlayer->v_Origin.DistTo(ent->m_vecOrigin()) < distance && player_tools::shouldTarget(ent) && !IsPlayerInvisible(ent))
|
||||
{
|
||||
distance = g_pLocalPlayer->v_Origin.DistTo(*ent->m_vecDormantOrigin());
|
||||
best_ent = ent;
|
||||
|
321
src/hacks/SpellForcer.cpp
Normal file
321
src/hacks/SpellForcer.cpp
Normal file
@ -0,0 +1,321 @@
|
||||
#include "common.hpp"
|
||||
#include "AntiCheatBypass.hpp"
|
||||
|
||||
namespace hacks::tf2::spellforcer
|
||||
{
|
||||
static settings::Boolean enabled("spellforce.enabled", "false");
|
||||
|
||||
static settings::Int default_spell("spellforce.default_spell", "-1");
|
||||
static settings::Int default_spell_rare("spellforce.default_spell.rare", "-1");
|
||||
static settings::Int default_spell_enemies("spellforce.default_spell.enemies", "-1");
|
||||
|
||||
static settings::Int doomsday_spell("spellforce.doomsday_spell", "-1");
|
||||
static settings::Int doomsday_spell_rare("spellforce.doomsday_spell.rare", "-1");
|
||||
static settings::Int doomsday_spell_enemies("spellforce.doomsday_spell.enemies", "-1");
|
||||
|
||||
static settings::Int helltower_spell("spellforce.helltower_spell", "-1");
|
||||
static settings::Int helltower_spell_enemies("spellforce.helltower_spell.enemies", "-1");
|
||||
|
||||
static settings::Int bumper_spell("spellforce.bumper_spell", "-1");
|
||||
static settings::Int bumper_spell_enemies("spellforce.bumper_spell.enemies", "-1");
|
||||
|
||||
static settings::Boolean debug_use_set_cmd("spellforce.debug.use_set_cmd", "false");
|
||||
static settings::Boolean debug_inverse_enemy("spellforce.debug.inverse-enemy", "false");
|
||||
|
||||
enum spelltypes
|
||||
{
|
||||
BUMPER_CARS = 0,
|
||||
DOOMSDAY = 1,
|
||||
HELLTOWER = 2,
|
||||
NORMAL = 3
|
||||
};
|
||||
|
||||
enum halloween_scenario
|
||||
{
|
||||
HALLOWEEN_SCENARIO_NONE = 0,
|
||||
HALLOWEEN_SCENARIO_MANN_MANOR,
|
||||
HALLOWEEN_SCENARIO_VIADUCT,
|
||||
HALLOWEEN_SCENARIO_LAKESIDE,
|
||||
HALLOWEEN_SCENARIO_HIGHTOWER,
|
||||
HALLOWEEN_SCENARIO_DOOMSDAY
|
||||
};
|
||||
|
||||
spelltypes getSpellMode()
|
||||
{
|
||||
if (HasCondition<TFCond_HalloweenKart>(LOCAL_E))
|
||||
return BUMPER_CARS;
|
||||
|
||||
int scenario = g_pGameRules->halloweenScenario;
|
||||
switch (scenario)
|
||||
{
|
||||
case HALLOWEEN_SCENARIO_DOOMSDAY:
|
||||
return DOOMSDAY;
|
||||
case HALLOWEEN_SCENARIO_HIGHTOWER:
|
||||
return HELLTOWER;
|
||||
default:
|
||||
return NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
// Too much random noise on these maps to force spells
|
||||
// static std::array<std::string, 1> noisy_maps{ "" };
|
||||
|
||||
static std::unordered_map<int, int> spellmap_normal({ { 0, 4206970 }, { 1, 4206969 }, { 2, 4206972 }, { 3, 4206997 }, { 4, 4206971 }, { 5, 4206977 }, { 7, 4206973 }, { 8, 4206982 }, { 9, 4206976 } });
|
||||
static std::unordered_map<int, int> spellmap_normal_rare({ { 7, 4206987 }, { 8, 4206982 }, { 9, 4207006 }, { 10, 4206983 }, { 11, 4206984 } });
|
||||
|
||||
static std::unordered_map<int, int> spellmap_helltower({ { 0, 4206998 }, { 1, 4206984 }, { 2, 4206985 }, { 3, 4206986 }, { 4, 4206987 }, { 5, 4206982 }, { 6, 4206983 } });
|
||||
|
||||
static std::unordered_map<int, int> spellmap_doomsday_normal({ { 0, 4206982 }, { 2, 4207006 }, { 4, 4206983 }, { 5, 4206984 } });
|
||||
static std::unordered_map<int, int> spellmap_doomsday_rare({ { 7, 4207009 }, { 8, 4207014 }, { 9, 4207008 }, { 10, 4207007 } });
|
||||
|
||||
static std::unordered_map<int, int> spellmap_bumpercar({ { 12, 4206982 }, { 13, 4206983 }, { 14, 4206987 }, { 15, 4206988 } });
|
||||
// static std::unordered_map<int, int> hasslecastle_normal({ { 0, 4206990 }, { 1, 4206989 }, { 2, 4206986 }, { 3, 4206997 }, { 4, 4206984 }, { 5, 4206983 }, { 7, 4207000 }, { 8, 4206982 }, { 9, 4207027 } });
|
||||
|
||||
int getCommandForSpellID(int spellidx, int spelltype)
|
||||
{
|
||||
std::unordered_map<int, int> spellmap;
|
||||
|
||||
// if (levelname.find("koth_slasher") != levelname.npos || levelname.find("pl_bloodwater") != levelname.npos || levelname.find("pl_rumble_event") != levelname.npos)
|
||||
|
||||
auto spellmode = getSpellMode();
|
||||
|
||||
switch (spellmode)
|
||||
{
|
||||
case HELLTOWER:
|
||||
spellmap = spellmap_helltower;
|
||||
break;
|
||||
case BUMPER_CARS:
|
||||
spellmap = spellmap_bumpercar;
|
||||
break;
|
||||
case DOOMSDAY:
|
||||
spellmap = spelltype ? spellmap_doomsday_rare : spellmap_doomsday_normal;
|
||||
break;
|
||||
default:
|
||||
spellmap = spelltype ? spellmap_normal_rare : spellmap_normal;
|
||||
}
|
||||
|
||||
int value = spellmap[spellidx];
|
||||
|
||||
// "No entry" should be returned as -1
|
||||
return value ? value : -1;
|
||||
}
|
||||
|
||||
// Doomsday spell list
|
||||
|
||||
static const int g_doomsdayNormalSpellIndexList[] = {
|
||||
0, // Fireball
|
||||
0, // Fireball x2
|
||||
2, // overheal
|
||||
4, // Jump
|
||||
5, // Stealth
|
||||
};
|
||||
|
||||
// Side note: 6 is the Teleport spell
|
||||
|
||||
static const int g_doomsdayRareSpellIndexList[] = {
|
||||
7, // Lightning
|
||||
8, // Mini
|
||||
9, // Meteor
|
||||
7, // Lightning
|
||||
8, // Mini
|
||||
9, // Meteor
|
||||
10 // Boss / Monoculus. Smaller chance
|
||||
};
|
||||
|
||||
// "Normal" Spell list
|
||||
static const int g_generalSpellIndexList[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 7, 8, 9 };
|
||||
|
||||
// Saves command that have a specific spell id
|
||||
std::unordered_map<int, int> command_to_spell_map;
|
||||
|
||||
int current_index = 0;
|
||||
|
||||
int getStaticCmd()
|
||||
{
|
||||
return 4206982 + current_index;
|
||||
}
|
||||
|
||||
CachedEntity *getClosestSpell()
|
||||
{
|
||||
CachedEntity *ent = nullptr;
|
||||
float best_dist = FLT_MAX;
|
||||
bool is_dormant = false;
|
||||
|
||||
if (CE_BAD(LOCAL_E) || !LOCAL_E->m_bAlivePlayer())
|
||||
return ent;
|
||||
for (int i = g_IEngine->GetMaxClients(); i < HIGHEST_ENTITY; i++)
|
||||
{
|
||||
CachedEntity *spell = ENTITY(i);
|
||||
if (CE_INVALID(spell) || !spell->m_vecDormantOrigin() || (spell->m_ItemType() != ITEM_SPELL && spell->m_ItemType() != ITEM_SPELL_RARE))
|
||||
continue;
|
||||
float dist = spell->m_flDistance();
|
||||
if (dist < best_dist || (is_dormant && !RAW_ENT(spell)->IsDormant() && dist <= 300.0f))
|
||||
{
|
||||
ent = spell;
|
||||
best_dist = dist;
|
||||
is_dormant = RAW_ENT(spell)->IsDormant();
|
||||
}
|
||||
}
|
||||
return ent;
|
||||
}
|
||||
|
||||
void CreateMoveLate()
|
||||
{
|
||||
if (hacks::tf2::antianticheat::enabled || !g_pGameRules->isUsingSpells_fn())
|
||||
return;
|
||||
auto cmd = 0;
|
||||
if (debug_use_set_cmd)
|
||||
cmd = getStaticCmd();
|
||||
else
|
||||
{
|
||||
auto spell = getClosestSpell();
|
||||
|
||||
// Apply bad effects for enemies
|
||||
if (debug_inverse_enemy || CE_BAD(spell) || spell->m_flDistance() > 300.0f)
|
||||
{
|
||||
int spellindex;
|
||||
|
||||
auto spellmode = getSpellMode();
|
||||
switch (spellmode)
|
||||
{
|
||||
case BUMPER_CARS:
|
||||
spellindex = *bumper_spell_enemies;
|
||||
break;
|
||||
case DOOMSDAY:
|
||||
spellindex = *doomsday_spell_enemies;
|
||||
break;
|
||||
case HELLTOWER:
|
||||
spellindex = *helltower_spell_enemies;
|
||||
break;
|
||||
case NORMAL:
|
||||
spellindex = *default_spell_enemies;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd = getCommandForSpellID(spellindex, 0);
|
||||
}
|
||||
else if (spell->m_ItemType() == ITEM_SPELL)
|
||||
{
|
||||
int spellindex;
|
||||
|
||||
auto spellmode = getSpellMode();
|
||||
switch (spellmode)
|
||||
{
|
||||
case BUMPER_CARS:
|
||||
spellindex = *bumper_spell;
|
||||
break;
|
||||
case DOOMSDAY:
|
||||
spellindex = *doomsday_spell;
|
||||
break;
|
||||
case HELLTOWER:
|
||||
spellindex = *helltower_spell;
|
||||
break;
|
||||
case NORMAL:
|
||||
spellindex = *default_spell;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd = getCommandForSpellID(spellindex, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int spellindex;
|
||||
|
||||
auto spellmode = getSpellMode();
|
||||
switch (spellmode)
|
||||
{
|
||||
case DOOMSDAY:
|
||||
spellindex = *doomsday_spell_rare;
|
||||
break;
|
||||
case HELLTOWER:
|
||||
case BUMPER_CARS:
|
||||
case NORMAL:
|
||||
spellindex = *default_spell_rare;
|
||||
break;
|
||||
}
|
||||
cmd = getCommandForSpellID(spellindex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd != -1)
|
||||
{
|
||||
current_late_user_cmd->command_number = cmd;
|
||||
current_late_user_cmd->random_seed = MD5_PseudoRandom(cmd) & 0x7FFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_VISUALS
|
||||
static Timer draw_timer;
|
||||
void Draw()
|
||||
{
|
||||
if (!enabled || !g_IEngine->IsInGame())
|
||||
{
|
||||
draw_timer.update();
|
||||
return;
|
||||
}
|
||||
static bool previously_highest = true;
|
||||
// Is the player the highest IDX of all players?
|
||||
bool is_player_highest = true;
|
||||
|
||||
int players_above = 0;
|
||||
|
||||
// Check if there is a valid player exceeding our IDX
|
||||
for (int i = g_pLocalPlayer->entity_idx + 1; i <= g_IEngine->GetMaxClients(); i++)
|
||||
{
|
||||
if (g_pPlayerResource->isValid(i))
|
||||
{
|
||||
is_player_highest = false;
|
||||
players_above++;
|
||||
}
|
||||
}
|
||||
if (is_player_highest != previously_highest)
|
||||
draw_timer.update();
|
||||
|
||||
previously_highest = is_player_highest;
|
||||
|
||||
if (!draw_timer.check(60000))
|
||||
{
|
||||
if (is_player_highest)
|
||||
AddCenterString("Forcing Spells.", colors::green);
|
||||
else
|
||||
AddCenterString(format("Cannot Force Spells, entity idx is ", players_above, " too low :("), colors::red);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CatCommand enter_spell_data("spellforcer_enter_data", "Debug",
|
||||
[](const CCommand &args)
|
||||
{
|
||||
if (args.ArgC() < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
// Grab spellidx
|
||||
int spellidx = std::stoi(args.Arg(1));
|
||||
|
||||
if (command_to_spell_map[spellidx] == 0)
|
||||
command_to_spell_map[spellidx] = getStaticCmd();
|
||||
for (auto &entry : command_to_spell_map)
|
||||
logging::Info("%d: %d", entry.first, entry.second);
|
||||
current_index++;
|
||||
}
|
||||
catch (const std::invalid_argument &)
|
||||
{
|
||||
logging::Info("Invalid Steamid32 provided.");
|
||||
}
|
||||
});
|
||||
|
||||
static InitRoutine init(
|
||||
[]()
|
||||
{
|
||||
#if ENABLE_VISUALS
|
||||
EC::Register(EC::Draw, Draw, "spellforcer_draw", EC::early);
|
||||
EC::Register(
|
||||
EC::LevelInit, []() { draw_timer.update(); }, "spellforcer_lvlinit");
|
||||
#endif
|
||||
EC::Register(EC::CreateMoveLate, CreateMoveLate, "spellforcer_cml", EC::early);
|
||||
});
|
||||
|
||||
} // namespace hacks::tf2::spellforcer
|
@ -45,6 +45,8 @@ static settings::Boolean warp_backwards{ "warp.on-hit.backwards", "false" };
|
||||
static settings::Boolean warp_left{ "warp.on-hit.left", "true" };
|
||||
static settings::Boolean warp_right{ "warp.on-hit.right", "true" };
|
||||
|
||||
static settings::Boolean debug_seqout{ "debug.warp_seqout", "false" };
|
||||
|
||||
// Hidden control rvars for communtiy servers
|
||||
static settings::Int maxusrcmdprocessticks("warp.maxusrcmdprocessticks", "24");
|
||||
|
||||
|
@ -10,10 +10,6 @@ namespace hooked_methods
|
||||
|
||||
DEFINE_HOOKED_METHOD(GetUserCmd, CUserCmd *, IInput *this_, int sequence_number)
|
||||
{
|
||||
// We need to overwrite this if crithack is on
|
||||
if (criticals::isEnabled())
|
||||
return &GetCmds(this_)[sequence_number % VERIFIED_CMD_SIZE];
|
||||
else
|
||||
return original::GetUserCmd(this_, sequence_number);
|
||||
return &GetCmds(this_)[sequence_number % VERIFIED_CMD_SIZE];
|
||||
}
|
||||
} // namespace hooked_methods
|
||||
|
@ -83,6 +83,9 @@ ItemManager::ItemManager() : mapper()
|
||||
RegisterModelMapping("models/items/crystal_ball_pickup_major.mdl", ITEM_SPELL_RARE);
|
||||
RegisterModelMapping("models/props_monster_mash/flask_vial_purple.mdl", ITEM_SPELL_RARE);
|
||||
|
||||
// Thanks valve
|
||||
RegisterSpecialMapping([](CachedEntity *ent) -> bool { return g_ItemManager.mapper.GetItemType(ent) == ITEM_SPELL && ent->m_iClassID() == CL_CLASS(CDynamicProp); }, ITEM_SPELL_RARE);
|
||||
|
||||
// == GHOSTS
|
||||
RegisterModelMapping("models/props_halloween/ghost.mdl", HALLOWEEN_GHOST);
|
||||
RegisterModelMapping("models/props_halloween/ghost_no_hat_red.mdl", HALLOWEEN_GHOST);
|
||||
@ -118,90 +121,93 @@ ItemManager::ItemManager() : mapper()
|
||||
RegisterModelMapping("models/items/medkit_overheal.mdl", ITEM_TF2C_PILL);
|
||||
// TF2C spawners
|
||||
|
||||
specials.push_back([](CachedEntity *entity) -> k_EItemType {
|
||||
static ItemModelMapper tf2c_weapon_mapper = []() -> ItemModelMapper {
|
||||
ItemModelMapper result;
|
||||
result.RegisterItem("models/weapons/w_models/w_bottle.mdl", ITEM_TF2C_W_BOTTLE);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_napalm.mdl", ITEM_TF2C_W_GRENADE_NAPALM);
|
||||
result.RegisterItem("models/weapons/w_models/w_supershotgun_mercenary.mdl", ITEM_TF2C_W_SUPERSHOTGUN_MERCENARY);
|
||||
result.RegisterItem("models/weapons/w_models/w_rocketbeta.mdl", ITEM_TF2C_W_ROCKETBETA);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_grenadelauncher.mdl", ITEM_TF2C_W_GRENADE_GRENADELAUNCHER);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenadelauncher.mdl", ITEM_TF2C_W_GRENADELAUNCHER);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_pipebomb.mdl", ITEM_TF2C_W_GRENADE_PIPEBOMB);
|
||||
result.RegisterItem("models/weapons/w_models/w_cigarette_case.mdl", ITEM_TF2C_W_CIGARETTE_CASE);
|
||||
result.RegisterItem("models/weapons/w_models/w_brandingiron.mdl", ITEM_TF2C_W_BRANDINGIRON);
|
||||
result.RegisterItem("models/weapons/w_models/w_banhammer.mdl", ITEM_TF2C_W_BANHAMMER);
|
||||
result.RegisterItem("models/weapons/w_models/w_sniperrifle.mdl", ITEM_TF2C_W_SNIPERRIFLE);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_heal.mdl", ITEM_TF2C_W_GRENADE_HEAL);
|
||||
result.RegisterItem("models/weapons/w_models/w_hammerfists.mdl", ITEM_TF2C_W_HAMMERFISTS);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_nail.mdl", ITEM_TF2C_W_GRENADE_NAIL);
|
||||
result.RegisterItem("models/weapons/w_models/w_dart.mdl", ITEM_TF2C_W_DART);
|
||||
result.RegisterItem("models/weapons/w_models/w_rpg.mdl", ITEM_TF2C_W_RPG);
|
||||
result.RegisterItem("models/weapons/w_models/w_umbrella_civilian.mdl", ITEM_TF2C_W_UMBRELLA_CIVILIAN);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_frag.mdl", ITEM_TF2C_W_GRENADE_FRAG);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_mirv.mdl", ITEM_TF2C_W_GRENADE_MIRV);
|
||||
result.RegisterItem("models/weapons/w_models/w_medigun.mdl", ITEM_TF2C_W_MEDIGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_mirv_demo.mdl", ITEM_TF2C_W_GRENADE_MIRV_DEMO);
|
||||
result.RegisterItem("models/weapons/w_models/w_pickaxe.mdl", ITEM_TF2C_W_PICKAXE);
|
||||
result.RegisterItem("models/weapons/w_models/w_syringegun.mdl", ITEM_TF2C_W_SYRINGEGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_scattergun.mdl", ITEM_TF2C_W_SCATTERGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_stengun.mdl", ITEM_TF2C_W_STENGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_snubnose.mdl", ITEM_TF2C_W_SNUBNOSE);
|
||||
result.RegisterItem("models/weapons/w_models/w_minigun.mdl", ITEM_TF2C_W_MINIGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_wrench.mdl", ITEM_TF2C_W_WRENCH);
|
||||
result.RegisterItem("models/weapons/w_models/w_bat.mdl", ITEM_TF2C_W_BAT);
|
||||
result.RegisterItem("models/weapons/w_models/w_sapper.mdl", ITEM_TF2C_W_SAPPER);
|
||||
result.RegisterItem("models/weapons/w_models/w_rocket.mdl", ITEM_TF2C_W_ROCKET);
|
||||
result.RegisterItem("models/weapons/w_models/w_hammer.mdl", ITEM_TF2C_W_HAMMER);
|
||||
result.RegisterItem("models/weapons/w_models/w_fishwhacker.mdl", ITEM_TF2C_W_FISHWHACKER);
|
||||
result.RegisterItem("models/weapons/w_models/w_kritzkrieg.mdl", ITEM_TF2C_W_KRITZKRIEG);
|
||||
result.RegisterItem("models/weapons/w_models/w_flaregun.mdl", ITEM_TF2C_W_FLAREGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_shovel.mdl", ITEM_TF2C_W_SHOVEL);
|
||||
result.RegisterItem("models/weapons/w_models/w_pistol.mdl", ITEM_TF2C_W_PISTOL);
|
||||
result.RegisterItem("models/weapons/w_models/w_smg.mdl", ITEM_TF2C_W_SMG);
|
||||
result.RegisterItem("models/weapons/w_models/w_leadpipe.mdl", ITEM_TF2C_W_LEADPIPE);
|
||||
result.RegisterItem("models/weapons/w_models/w_flaregun_shell.mdl", ITEM_TF2C_W_FLAREGUN_SHELL);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_emp.mdl", ITEM_TF2C_W_GRENADE_EMP);
|
||||
result.RegisterItem("models/weapons/w_models/w_cyclops.mdl", ITEM_TF2C_W_CYCLOPS);
|
||||
result.RegisterItem("models/weapons/w_models/w_machete.mdl", ITEM_TF2C_W_MACHETE);
|
||||
result.RegisterItem("models/weapons/w_models/w_shotgun.mdl", ITEM_TF2C_W_SHOTGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_revolver.mdl", ITEM_TF2C_W_REVOLVER);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_gas.mdl", ITEM_TF2C_W_GRENADE_GAS);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_beartrap.mdl", ITEM_TF2C_W_GRENADE_BEARTRAP);
|
||||
result.RegisterItem("models/weapons/w_models/w_fireaxe.mdl", ITEM_TF2C_W_FIREAXE);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_conc.mdl", ITEM_TF2C_W_GRENADE_CONC);
|
||||
result.RegisterItem("models/weapons/w_models/w_nailgun.mdl", ITEM_TF2C_W_NAILGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_bonesaw.mdl", ITEM_TF2C_W_BONESAW);
|
||||
result.RegisterItem("models/weapons/w_models/w_stickybomb_launcher.mdl", ITEM_TF2C_W_STICKYBOMB_LAUNCHER);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_bomblet.mdl", ITEM_TF2C_W_GRENADE_BOMBLET);
|
||||
result.RegisterItem("models/weapons/w_models/w_tranq.mdl", ITEM_TF2C_W_TRANQ);
|
||||
result.RegisterItem("models/weapons/w_models/w_dynamite.mdl", ITEM_TF2C_W_DYNAMITE);
|
||||
result.RegisterItem("models/weapons/w_models/w_club.mdl", ITEM_TF2C_W_CLUB);
|
||||
result.RegisterItem("models/weapons/w_models/w_tommygun.mdl", ITEM_TF2C_W_TOMMYGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_coffepot.mdl", ITEM_TF2C_W_COFFEPOT);
|
||||
result.RegisterItem("models/weapons/w_models/w_stickybomb.mdl", ITEM_TF2C_W_STICKYBOMB);
|
||||
result.RegisterItem("models/weapons/w_models/w_rocketlauncher.mdl", ITEM_TF2C_W_ROCKETLAUNCHER);
|
||||
result.RegisterItem("models/weapons/w_models/w_flamethrower.mdl", ITEM_TF2C_W_FLAMETHROWER);
|
||||
result.RegisterItem("models/weapons/w_models/w_crowbar.mdl", ITEM_TF2C_W_CROWBAR);
|
||||
result.RegisterItem("models/weapons/w_models/w_builder.mdl", ITEM_TF2C_W_BUILDER);
|
||||
result.RegisterItem("models/weapons/w_models/w_heavy_artillery.mdl", ITEM_TF2C_W_HEAVY_ARTILLERY);
|
||||
result.RegisterItem("models/weapons/w_models/w_knife.mdl", ITEM_TF2C_W_KNIFE);
|
||||
result.RegisterItem("models/weapons/w_models/w_pda_engineer.mdl", ITEM_TF2C_W_PDA_ENGINEER);
|
||||
result.RegisterItem("models/weapons/w_models/w_bottle_broken.mdl", ITEM_TF2C_W_BOTTLE_BROKEN);
|
||||
result.RegisterItem("models/weapons/w_models/w_toolbox.mdl", ITEM_TF2C_W_TOOLBOX);
|
||||
result.RegisterItem("models/weapons/w_models/w_syringe_proj.mdl", ITEM_TF2C_W_SYRINGE_PROJ);
|
||||
result.RegisterItem("models/weapons/w_models/w_nail.mdl", ITEM_TF2C_W_NAIL);
|
||||
result.RegisterItem("models/weapons/w_models/w_syringe.mdl", ITEM_TF2C_W_SYRINGE);
|
||||
result.RegisterItem("models/weapons/w_models/w_overhealer.mdl", ITEM_TF2C_W_OVERHEALER);
|
||||
return result;
|
||||
}();
|
||||
|
||||
if (entity->m_iClassID() == CL_CLASS(CWeaponSpawner))
|
||||
specials.push_back(
|
||||
[](CachedEntity *entity) -> k_EItemType
|
||||
{
|
||||
return tf2c_weapon_mapper.GetItemType(entity);
|
||||
}
|
||||
return ITEM_NONE;
|
||||
});
|
||||
static ItemModelMapper tf2c_weapon_mapper = []() -> ItemModelMapper
|
||||
{
|
||||
ItemModelMapper result;
|
||||
result.RegisterItem("models/weapons/w_models/w_bottle.mdl", ITEM_TF2C_W_BOTTLE);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_napalm.mdl", ITEM_TF2C_W_GRENADE_NAPALM);
|
||||
result.RegisterItem("models/weapons/w_models/w_supershotgun_mercenary.mdl", ITEM_TF2C_W_SUPERSHOTGUN_MERCENARY);
|
||||
result.RegisterItem("models/weapons/w_models/w_rocketbeta.mdl", ITEM_TF2C_W_ROCKETBETA);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_grenadelauncher.mdl", ITEM_TF2C_W_GRENADE_GRENADELAUNCHER);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenadelauncher.mdl", ITEM_TF2C_W_GRENADELAUNCHER);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_pipebomb.mdl", ITEM_TF2C_W_GRENADE_PIPEBOMB);
|
||||
result.RegisterItem("models/weapons/w_models/w_cigarette_case.mdl", ITEM_TF2C_W_CIGARETTE_CASE);
|
||||
result.RegisterItem("models/weapons/w_models/w_brandingiron.mdl", ITEM_TF2C_W_BRANDINGIRON);
|
||||
result.RegisterItem("models/weapons/w_models/w_banhammer.mdl", ITEM_TF2C_W_BANHAMMER);
|
||||
result.RegisterItem("models/weapons/w_models/w_sniperrifle.mdl", ITEM_TF2C_W_SNIPERRIFLE);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_heal.mdl", ITEM_TF2C_W_GRENADE_HEAL);
|
||||
result.RegisterItem("models/weapons/w_models/w_hammerfists.mdl", ITEM_TF2C_W_HAMMERFISTS);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_nail.mdl", ITEM_TF2C_W_GRENADE_NAIL);
|
||||
result.RegisterItem("models/weapons/w_models/w_dart.mdl", ITEM_TF2C_W_DART);
|
||||
result.RegisterItem("models/weapons/w_models/w_rpg.mdl", ITEM_TF2C_W_RPG);
|
||||
result.RegisterItem("models/weapons/w_models/w_umbrella_civilian.mdl", ITEM_TF2C_W_UMBRELLA_CIVILIAN);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_frag.mdl", ITEM_TF2C_W_GRENADE_FRAG);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_mirv.mdl", ITEM_TF2C_W_GRENADE_MIRV);
|
||||
result.RegisterItem("models/weapons/w_models/w_medigun.mdl", ITEM_TF2C_W_MEDIGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_mirv_demo.mdl", ITEM_TF2C_W_GRENADE_MIRV_DEMO);
|
||||
result.RegisterItem("models/weapons/w_models/w_pickaxe.mdl", ITEM_TF2C_W_PICKAXE);
|
||||
result.RegisterItem("models/weapons/w_models/w_syringegun.mdl", ITEM_TF2C_W_SYRINGEGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_scattergun.mdl", ITEM_TF2C_W_SCATTERGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_stengun.mdl", ITEM_TF2C_W_STENGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_snubnose.mdl", ITEM_TF2C_W_SNUBNOSE);
|
||||
result.RegisterItem("models/weapons/w_models/w_minigun.mdl", ITEM_TF2C_W_MINIGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_wrench.mdl", ITEM_TF2C_W_WRENCH);
|
||||
result.RegisterItem("models/weapons/w_models/w_bat.mdl", ITEM_TF2C_W_BAT);
|
||||
result.RegisterItem("models/weapons/w_models/w_sapper.mdl", ITEM_TF2C_W_SAPPER);
|
||||
result.RegisterItem("models/weapons/w_models/w_rocket.mdl", ITEM_TF2C_W_ROCKET);
|
||||
result.RegisterItem("models/weapons/w_models/w_hammer.mdl", ITEM_TF2C_W_HAMMER);
|
||||
result.RegisterItem("models/weapons/w_models/w_fishwhacker.mdl", ITEM_TF2C_W_FISHWHACKER);
|
||||
result.RegisterItem("models/weapons/w_models/w_kritzkrieg.mdl", ITEM_TF2C_W_KRITZKRIEG);
|
||||
result.RegisterItem("models/weapons/w_models/w_flaregun.mdl", ITEM_TF2C_W_FLAREGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_shovel.mdl", ITEM_TF2C_W_SHOVEL);
|
||||
result.RegisterItem("models/weapons/w_models/w_pistol.mdl", ITEM_TF2C_W_PISTOL);
|
||||
result.RegisterItem("models/weapons/w_models/w_smg.mdl", ITEM_TF2C_W_SMG);
|
||||
result.RegisterItem("models/weapons/w_models/w_leadpipe.mdl", ITEM_TF2C_W_LEADPIPE);
|
||||
result.RegisterItem("models/weapons/w_models/w_flaregun_shell.mdl", ITEM_TF2C_W_FLAREGUN_SHELL);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_emp.mdl", ITEM_TF2C_W_GRENADE_EMP);
|
||||
result.RegisterItem("models/weapons/w_models/w_cyclops.mdl", ITEM_TF2C_W_CYCLOPS);
|
||||
result.RegisterItem("models/weapons/w_models/w_machete.mdl", ITEM_TF2C_W_MACHETE);
|
||||
result.RegisterItem("models/weapons/w_models/w_shotgun.mdl", ITEM_TF2C_W_SHOTGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_revolver.mdl", ITEM_TF2C_W_REVOLVER);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_gas.mdl", ITEM_TF2C_W_GRENADE_GAS);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_beartrap.mdl", ITEM_TF2C_W_GRENADE_BEARTRAP);
|
||||
result.RegisterItem("models/weapons/w_models/w_fireaxe.mdl", ITEM_TF2C_W_FIREAXE);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_conc.mdl", ITEM_TF2C_W_GRENADE_CONC);
|
||||
result.RegisterItem("models/weapons/w_models/w_nailgun.mdl", ITEM_TF2C_W_NAILGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_bonesaw.mdl", ITEM_TF2C_W_BONESAW);
|
||||
result.RegisterItem("models/weapons/w_models/w_stickybomb_launcher.mdl", ITEM_TF2C_W_STICKYBOMB_LAUNCHER);
|
||||
result.RegisterItem("models/weapons/w_models/w_grenade_bomblet.mdl", ITEM_TF2C_W_GRENADE_BOMBLET);
|
||||
result.RegisterItem("models/weapons/w_models/w_tranq.mdl", ITEM_TF2C_W_TRANQ);
|
||||
result.RegisterItem("models/weapons/w_models/w_dynamite.mdl", ITEM_TF2C_W_DYNAMITE);
|
||||
result.RegisterItem("models/weapons/w_models/w_club.mdl", ITEM_TF2C_W_CLUB);
|
||||
result.RegisterItem("models/weapons/w_models/w_tommygun.mdl", ITEM_TF2C_W_TOMMYGUN);
|
||||
result.RegisterItem("models/weapons/w_models/w_coffepot.mdl", ITEM_TF2C_W_COFFEPOT);
|
||||
result.RegisterItem("models/weapons/w_models/w_stickybomb.mdl", ITEM_TF2C_W_STICKYBOMB);
|
||||
result.RegisterItem("models/weapons/w_models/w_rocketlauncher.mdl", ITEM_TF2C_W_ROCKETLAUNCHER);
|
||||
result.RegisterItem("models/weapons/w_models/w_flamethrower.mdl", ITEM_TF2C_W_FLAMETHROWER);
|
||||
result.RegisterItem("models/weapons/w_models/w_crowbar.mdl", ITEM_TF2C_W_CROWBAR);
|
||||
result.RegisterItem("models/weapons/w_models/w_builder.mdl", ITEM_TF2C_W_BUILDER);
|
||||
result.RegisterItem("models/weapons/w_models/w_heavy_artillery.mdl", ITEM_TF2C_W_HEAVY_ARTILLERY);
|
||||
result.RegisterItem("models/weapons/w_models/w_knife.mdl", ITEM_TF2C_W_KNIFE);
|
||||
result.RegisterItem("models/weapons/w_models/w_pda_engineer.mdl", ITEM_TF2C_W_PDA_ENGINEER);
|
||||
result.RegisterItem("models/weapons/w_models/w_bottle_broken.mdl", ITEM_TF2C_W_BOTTLE_BROKEN);
|
||||
result.RegisterItem("models/weapons/w_models/w_toolbox.mdl", ITEM_TF2C_W_TOOLBOX);
|
||||
result.RegisterItem("models/weapons/w_models/w_syringe_proj.mdl", ITEM_TF2C_W_SYRINGE_PROJ);
|
||||
result.RegisterItem("models/weapons/w_models/w_nail.mdl", ITEM_TF2C_W_NAIL);
|
||||
result.RegisterItem("models/weapons/w_models/w_syringe.mdl", ITEM_TF2C_W_SYRINGE);
|
||||
result.RegisterItem("models/weapons/w_models/w_overhealer.mdl", ITEM_TF2C_W_OVERHEALER);
|
||||
return result;
|
||||
}();
|
||||
|
||||
if (entity->m_iClassID() == CL_CLASS(CWeaponSpawner))
|
||||
{
|
||||
return tf2c_weapon_mapper.GetItemType(entity);
|
||||
}
|
||||
return ITEM_NONE;
|
||||
});
|
||||
}
|
||||
|
||||
void ItemManager::RegisterModelMapping(std::string path, k_EItemType type)
|
||||
@ -266,7 +272,9 @@ k_EItemType ItemModelMapper::GetItemType(CachedEntity *entity)
|
||||
}
|
||||
|
||||
ItemManager g_ItemManager;
|
||||
static InitRoutine init_itemtypes([]() {
|
||||
EC::Register(
|
||||
EC::LevelInit, []() { g_ItemManager = ItemManager{}; }, "clear_itemtypes");
|
||||
});
|
||||
static InitRoutine init_itemtypes(
|
||||
[]()
|
||||
{
|
||||
EC::Register(
|
||||
EC::LevelInit, []() { g_ItemManager = ItemManager{}; }, "clear_itemtypes");
|
||||
});
|
||||
|
@ -609,7 +609,7 @@ void CL_SendMove_hook()
|
||||
current_weapon_spread = 0.0;
|
||||
|
||||
// first try to get the player and check if he is valid
|
||||
if (!RAW_ENT(LOCAL_E))
|
||||
if (!RAW_ENT(LOCAL_E) || HasCondition<TFCond_HalloweenGhostMode>(LOCAL_E))
|
||||
{
|
||||
// don't set called_from_sendmove here cuz we don't care
|
||||
CL_SendMove_t original = (CL_SendMove_t) cl_nospread_sendmovedetour.GetOriginalFunc();
|
||||
|
@ -190,6 +190,16 @@ bool TFPlayerResource::isAlive(int idx)
|
||||
return *(bool *) ((unsigned) ent + netvar.res_bAlive + idx);
|
||||
}
|
||||
|
||||
bool TFPlayerResource::isValid(int idx)
|
||||
{
|
||||
IClientEntity *ent = g_IEntityList->GetClientEntity(entity);
|
||||
if (!ent || ent->GetClientClass()->m_ClassID != RCC_PLAYERRESOURCE)
|
||||
return 0;
|
||||
if (idx >= MAX_PLAYERS || idx < 0)
|
||||
return false;
|
||||
return *(bool *) ((unsigned) ent + netvar.res_bValid + idx);
|
||||
}
|
||||
|
||||
int TFPlayerResource::getClass(int idx)
|
||||
{
|
||||
IClientEntity *ent = g_IEntityList->GetClientEntity(entity);
|
||||
|
Reference in New Issue
Block a user