diff --git a/data/menu/nullifiedcat/visuals/esp.xml b/data/menu/nullifiedcat/visuals/esp.xml index 2fbf941c..d95795ec 100755 --- a/data/menu/nullifiedcat/visuals/esp.xml +++ b/data/menu/nullifiedcat/visuals/esp.xml @@ -17,14 +17,17 @@ - + - + + + + diff --git a/include/core/netvars.hpp b/include/core/netvars.hpp index be4fb062..47b531be 100644 --- a/include/core/netvars.hpp +++ b/include/core/netvars.hpp @@ -202,6 +202,7 @@ public: offset_t m_iPlayerLevel_Resource; offset_t m_iPlayerIndex; + offset_t m_hTargetPlayer; }; extern NetVars netvar; diff --git a/include/entitycache.hpp b/include/entitycache.hpp index a4dcd27e..7785111d 100644 --- a/include/entitycache.hpp +++ b/include/entitycache.hpp @@ -157,6 +157,8 @@ public: ret = ENTITY_PROJECTILE; else if (classid == CL_CLASS(CObjectTeleporter) || classid == CL_CLASS(CObjectSentrygun) || classid == CL_CLASS(CObjectDispenser)) ret = ENTITY_BUILDING; + else if (classid == CL_CLASS(CZombie) || classid == CL_CLASS(CTFTankBoss) || classid == CL_CLASS(CMerasmus) || classid == CL_CLASS(CMerasmusDancer) || classid == CL_CLASS(CEyeballBoss) || classid == CL_CLASS(CHeadlessHatman)) + ret = ENTITY_NPC; else ret = ENTITY_GENERIC; return ret; diff --git a/include/enums.hpp b/include/enums.hpp index d9bb8c1b..7a0e9894 100755 --- a/include/enums.hpp +++ b/include/enums.hpp @@ -12,7 +12,8 @@ enum EntityType ENTITY_GENERIC, ENTITY_PLAYER, ENTITY_BUILDING, - ENTITY_PROJECTILE + ENTITY_PROJECTILE, + ENTITY_NPC }; enum powerup_type @@ -102,4 +103,4 @@ enum hitbox_t hip_R = 15, knee_R = 16, foot_R = 17 -}; \ No newline at end of file +}; diff --git a/include/helpers.hpp b/include/helpers.hpp index 129bb0cd..5a6638d6 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -227,3 +227,5 @@ template std::string format(const Args &... args) extern const std::string classes[10]; extern const char *powerups[POWERUP_COUNT]; +bool isTruce(); +void setTruce(bool status); diff --git a/include/itemtypes.hpp b/include/itemtypes.hpp index 306abd5f..7c657bfb 100644 --- a/include/itemtypes.hpp +++ b/include/itemtypes.hpp @@ -24,6 +24,7 @@ enum k_EItemType ITEM_AMMO_SMALL, ITEM_AMMO_MEDIUM, ITEM_AMMO_LARGE, + ITEM_CRUMPKIN, ITEM_POWERUP_STRENGTH, ITEM_POWERUP_RESISTANCE, @@ -42,6 +43,14 @@ enum k_EItemType ITEM_POWERUP_FIRST = ITEM_POWERUP_STRENGTH, ITEM_POWERUP_LAST = ITEM_POWERUP_CRITS, + HALLOWEEN_GHOST, + HALLOWEEN_GHOST_NOHAT_RED, + HALLOWEEN_GHOST_NOHAT, + + BOMB_BALLOONBOMB, + BOMB_WOODENBARREL, + BOMB_WALKEREXPLODE, + ITEM_TF2C_PILL, ITEM_TF2C_CRITS, diff --git a/include/sdk/CGameRules.h b/include/sdk/CGameRules.h index 770781ff..1ffa240a 100755 --- a/include/sdk/CGameRules.h +++ b/include/sdk/CGameRules.h @@ -6,12 +6,11 @@ */ #pragma once - class CGameRules { public: - int unknown_pad_0[12]; - int roundmode; - int unknown_pad_1[1]; - int winning_team; + int pad0[12]; // 0 | 48 bytes | 48 + int roundmode; // 48 | 4 bytes | 52 + int pad1[1]; // 52 | 4 bytes | 56 + int winning_team; // 56 | 4 bytes | 60 }; diff --git a/src/PlayerTools.cpp b/src/PlayerTools.cpp index a8f15b70..64ecc308 100644 --- a/src/PlayerTools.cpp +++ b/src/PlayerTools.cpp @@ -49,8 +49,15 @@ bool shouldTarget(CachedEntity *entity) return false; if (HasCondition(entity)) return false; + // Don't shoot players in truce + if (isTruce()) + return false; return shouldTargetSteamId(entity->player_info.friendsID); } + else if (entity->m_Type() == ENTITY_BUILDING) + // Don't shoot buildings in truce + if (isTruce()) + return false; return true; } diff --git a/src/core/netvars.cpp b/src/core/netvars.cpp index 84e54551..7bee11ed 100644 --- a/src/core/netvars.cpp +++ b/src/core/netvars.cpp @@ -149,6 +149,9 @@ void NetVars::Init() this->m_iHealingAssist_Resource = gNetvars.get_offset("DT_TFPlayerResource", "m_iHealingAssist"); this->m_iPlayerLevel_Resource = gNetvars.get_offset("DT_TFPlayerResource", "m_iPlayerLevel"); this->m_iPlayerIndex = gNetvars.get_offset("DT_TFRagdoll", "m_iPlayerIndex"); + + // Gargoyle + this->m_hTargetPlayer = gNetvars.get_offset("DT_CHalloweenGiftPickup", "m_hTargetPlayer"); } IF_GAME(IsTF2C()) { diff --git a/src/hacks/Aimbot.cpp b/src/hacks/Aimbot.cpp index b0ceeb5f..ccc81799 100644 --- a/src/hacks/Aimbot.cpp +++ b/src/hacks/Aimbot.cpp @@ -77,6 +77,7 @@ static settings::Boolean ignore_vaccinator{ "aimbot.target.ignore-vaccinator", " static settings::Boolean ignore_deadringer{ "aimbot.target.ignore-deadringer", "1" }; static settings::Boolean buildings_sentry{ "aimbot.target.sentry", "1" }; static settings::Boolean buildings_other{ "aimbot.target.other-buildings", "1" }; +static settings::Boolean npcs{ "aimbot.target.npcs", "1" }; static settings::Boolean stickybot{ "aimbot.target.stickybomb", "0" }; static settings::Boolean rageonly{ "aimbot.target.ignore-non-rage", "0" }; static settings::Int teammates{ "aimbot.target.teammates", "0" }; @@ -141,7 +142,7 @@ int GetSentry() CachedEntity *ent = ENTITY(i); if (CE_BAD(ent)) continue; - if ((ent->m_Type() != ENTITY_BUILDING && ent->m_iClassID() != CL_CLASS(CTFTankBoss)) || ent->m_iClassID() != CL_CLASS(CObjectSentrygun)) + if (ent->m_Type() != ENTITY_BUILDING || ent->m_iClassID() != CL_CLASS(CObjectSentrygun)) continue; if ((CE_INT(ent, netvar.m_hBuilder) & 0xFFF) != g_pLocalPlayer->entity_idx) continue; @@ -745,10 +746,9 @@ bool IsTargetStateGood(CachedEntity *entity) return false; return true; - - // Check for buildings } - else if (entity->m_Type() == ENTITY_BUILDING || entity->m_iClassID() == CL_CLASS(CTFTankBoss)) + // Check for buildings + else if (entity->m_Type() == ENTITY_BUILDING) { // Don't aim if holding sapper if (g_pLocalPlayer->holding_sapper) @@ -803,9 +803,39 @@ bool IsTargetStateGood(CachedEntity *entity) return false; return true; - - // Check for stickybombs } + // NPCs (Skeletons, Merasmus, etc) + else if (entity->m_Type() == ENTITY_NPC) + { + // Sapper aimbot? no. + if (g_pLocalPlayer->holding_sapper) + return false; + + // NPC targeting is disabled + if (!npcs) + return false; + + // Cannot shoot this + if (entity->m_iTeam() == LOCAL_E->m_iTeam()) + return false; + + // Distance + if (EffectiveTargetingRange()) + { + if (entity->m_flDistance() > (int) EffectiveTargetingRange()) + return false; + } + + // Grab the prediction var + AimbotCalculatedData_s &cd = calculated_data_array[entity->m_IDX]; + + if (!VischeckPredictedEntity(entity)) + return false; + if (fov > 0.0f && cd.fov > fov) + return false; + return true; + } + // Check for stickybombs else if (entity->m_iClassID() == CL_CLASS(CTFGrenadePipebombProjectile)) { // Enabled @@ -885,7 +915,7 @@ void Aim(CachedEntity *entity) Vector angles = GetAimAtAngles(g_pLocalPlayer->v_Eye, PredictEntity(entity)); // Multipoint - if (multipoint && !projectile_mode) + if (multipoint && !projectile_mode && entity->m_Type() == ENTITY_PLAYER) { // Get hitbox num AimbotCalculatedData_s &cd = calculated_data_array[entity->m_IDX]; @@ -894,7 +924,7 @@ void Aim(CachedEntity *entity) auto hitboxmin = hb->min; auto hitboxmax = hb->max; auto hitboxcenter = hb->center; - if (shouldBacktrack() && entity->m_Type() == ENTITY_PLAYER) + if (shouldBacktrack()) { // This does vischecks and everything auto data = hacks::tf2::backtrack::getClosestEntTick(entity, LOCAL_E->m_vecOrigin(), aimbotTickFilter); @@ -1100,16 +1130,23 @@ const Vector &PredictEntity(CachedEntity *entity) else GetHitbox(entity, cd.hitbox, result); } - // Buildings } - else if (entity->m_Type() == ENTITY_BUILDING || entity->m_iClassID() != CL_CLASS(CTFTankBoss)) + // Buildings + else if (entity->m_Type() == ENTITY_BUILDING) { if (cur_proj_grav || cur_proj_grav) result = BuildingPrediction(entity, GetBuildingPosition(entity), cur_proj_speed, cur_proj_grav, cur_proj_start_vel); else result = GetBuildingPosition(entity); - // Other } + // NPCs (Skeletons, merasmus, etc) + else if (entity->m_Type() == ENTITY_NPC) + { + auto mins = RAW_ENT(entity)->GetCollideable()->OBBMins(); + auto maxs = RAW_ENT(entity)->GetCollideable()->OBBMaxs(); + result = RAW_ENT(entity)->GetCollideable()->GetCollisionOrigin() + (mins + maxs) / 2.0f; + } + // Other else { result = entity->m_vecOrigin(); diff --git a/src/hacks/ESP.cpp b/src/hacks/ESP.cpp index 60d69c2b..ddc27d38 100644 --- a/src/hacks/ESP.cpp +++ b/src/hacks/ESP.cpp @@ -1,4 +1,4 @@ -/* +/* * HEsp.cpp * * Created on: Oct 6, 2016 @@ -40,7 +40,7 @@ static settings::Boolean legit{ "esp.legit", "false" }; static settings::Boolean local_esp{ "esp.show.local", "true" }; static settings::Boolean buildings{ "esp.show.buildings", "true" }; static settings::Boolean teammates{ "esp.show.teammates", "true" }; -static settings::Boolean tank{ "esp.show.tank", "true" }; +static settings::Boolean npc{ "esp.show.npc", "true" }; static settings::Boolean show_weapon{ "esp.info.weapon", "false" }; static settings::Boolean show_distance{ "esp.info.distance", "true" }; @@ -60,6 +60,9 @@ static settings::Boolean item_powerups{ "esp.item.powerup", "true" }; static settings::Boolean item_money{ "esp.item.money", "true" }; static settings::Boolean item_money_red{ "esp.item.money-red", "false" }; static settings::Boolean item_spellbooks{ "esp.item.spellbook", "true" }; +static settings::Boolean item_explosive{ "esp.item.explosive", "true" }; +static settings::Boolean item_crumpkin{ "esp.item.crumpkin", "true" }; +static settings::Boolean item_gargoyle{ "esp.item.gargoyle", "true" }; // TF2C static settings::Boolean item_weapon_spawners{ "esp.item.weapon-spawner", "true" }; static settings::Boolean item_adrenaline{ "esp.item.adrenaline", "true" }; @@ -248,6 +251,17 @@ const std::string health_small_str = "Small Medkit"; const std::string mvm_money_str = "Money"; const std::string mvm_red_money_str = "~Money~"; const std::string tank_str = "Tank"; +const std::string merasmus_str = "Merasmus"; +const std::string monoculus_str = "Monoculus"; +const std::string horsemann_str = "Horsemann"; +const std::string skeleton_str = "Skeleton"; +const std::string ghost_str = "Ghost"; +const std::string pumpkinbomb_str = "Pumpkin Bomb"; +const std::string crumpkin_str = "Crumpkin"; +const std::string gargoyle_str = "Gargoyle"; +const std::string balloonbomb_str = "Dynamite Balloon"; +const std::string woodenbarrel_str = "Explosive Barrel"; +const std::string walkerexplode_str = "Alien Walker"; const std::string rpg_str = "RPG"; const std::string smg_str = "SMG"; const std::string shotgun_str = "Shotgun"; @@ -1022,7 +1036,6 @@ void _FASTCALL ProcessEntity(CachedEntity *ent) // Projectile esp if (ent->m_Type() == ENTITY_PROJECTILE && proj_esp && (ent->m_bEnemy() || (teammates && !proj_enemy))) { - // Rockets if (classid == CL_CLASS(CTFProjectile_Rocket) || classid == CL_CLASS(CTFProjectile_SentryRocket)) { @@ -1104,22 +1117,147 @@ void _FASTCALL ProcessEntity(CachedEntity *ent) } } } - int itemtype = ent->m_ItemType(); - // Tank esp - if (classid == CL_CLASS(CTFTankBoss) && tank) + // NPC esp + if (npc) + { + // We can mark everything except the ghost like this + if (ent->m_Type() == ENTITY_NPC) + { + switch (classid) + { + case CL_CLASS(CTFTankBoss): + AddEntityString(ent, tank_str, colors::FromRGBA8(0, 128, 0, 255)); + break; + case CL_CLASS(CMerasmus): + case CL_CLASS(CMerasmusDancer): + AddEntityString(ent, merasmus_str, colors::FromRGBA8(0, 128, 0, 255)); + break; + case CL_CLASS(CZombie): + AddEntityString(ent, skeleton_str, colors::FromRGBA8(0, 128, 0, 255)); + break; + case CL_CLASS(CEyeballBoss): + AddEntityString(ent, monoculus_str, colors::FromRGBA8(0, 128, 0, 255)); + break; + case CL_CLASS(CHeadlessHatman): + AddEntityString(ent, horsemann_str, colors::FromRGBA8(0, 128, 0, 255)); + break; + } + } + else + { + switch (itemtype) + { + case HALLOWEEN_GHOST: + case HALLOWEEN_GHOST_NOHAT_RED: + case HALLOWEEN_GHOST_NOHAT: + AddEntityString(ent, ghost_str, colors::FromRGBA8(0, 128, 0, 255)); + } + } + } + if (item_esp) { - AddEntityString(ent, tank_str); - // Dropped weapon esp - } - else if (classid == CL_CLASS(CTFDroppedWeapon) && item_esp && item_dropped_weapons) - { - AddEntityString(ent, std::string("Dropped Weapon")); //I've never seen this not being "WEAPON CTFDroppedWeapon" so why not make it prettier? + if (item_dropped_weapons && classid == CL_CLASS(CTFDroppedWeapon)) + { + AddEntityString(ent, std::string("Dropped Weapon")); + } + // Gargoyle esp + else if (item_gargoyle && classid == CL_CLASS(CHalloweenGiftPickup)) + { + if (HandleToIDX(CE_INT(ent, netvar.m_hTargetPlayer)) == g_pLocalPlayer->entity_idx) + { + AddEntityString(ent, gargoyle_str, colors::FromRGBA8(98, 163, 213, 255)); + } + } + // Explosive/Environmental hazard esp + else if (item_explosive && (classid == CL_CLASS(CTFPumpkinBomb) || itemtype == BOMB_BALLOONBOMB || itemtype == BOMB_WOODENBARREL || itemtype == BOMB_WALKEREXPLODE)) + { + if (classid == CL_CLASS(CTFPumpkinBomb)) + AddEntityString(ent, pumpkinbomb_str, colors::FromRGBA8(255, 162, 0, 255)); + else + { + switch (itemtype) + { + case BOMB_BALLOONBOMB: + AddEntityString(ent, balloonbomb_str, colors::FromRGBA8(255, 162, 0, 255)); + break; + case BOMB_WOODENBARREL: + AddEntityString(ent, woodenbarrel_str, colors::FromRGBA8(255, 162, 0, 255)); + break; + case BOMB_WALKEREXPLODE: + AddEntityString(ent, walkerexplode_str, colors::FromRGBA8(255, 162, 0, 255)); + break; + } + } + } + // Other item esp + else if (itemtype != ITEM_NONE) + { + // Health pack esp + if (item_health_packs && (itemtype >= ITEM_HEALTH_SMALL && itemtype <= ITEM_HEALTH_LARGE || itemtype == ITEM_HL_BATTERY)) + { + if (itemtype == ITEM_HEALTH_SMALL) + AddEntityString(ent, health_small_str); + if (itemtype == ITEM_HEALTH_MEDIUM) + AddEntityString(ent, health_medium_str); + if (itemtype == ITEM_HEALTH_LARGE) + AddEntityString(ent, health_big_str); + if (itemtype == ITEM_HL_BATTERY) + AddEntityString(ent, hl_battery_str); - // MVM Money esp + // TF2C Adrenaline esp + } + else if (item_adrenaline && itemtype == ITEM_TF2C_PILL) + { + AddEntityString(ent, pill_str); + + // Ammo pack esp + } + else if (item_ammo_packs && itemtype >= ITEM_AMMO_SMALL && itemtype <= ITEM_AMMO_LARGE) + { + if (itemtype == ITEM_AMMO_SMALL) + AddEntityString(ent, ammo_small_str); + if (itemtype == ITEM_AMMO_MEDIUM) + AddEntityString(ent, ammo_medium_str); + if (itemtype == ITEM_AMMO_LARGE) + AddEntityString(ent, ammo_big_str); + + // Powerup esp + } + else if (item_powerups && itemtype >= ITEM_POWERUP_FIRST && itemtype <= ITEM_POWERUP_LAST) + { + AddEntityString(ent, std::string(powerups[itemtype - ITEM_POWERUP_FIRST])); + + // TF2C weapon spawner esp + } + else if (item_weapon_spawners && itemtype >= ITEM_TF2C_W_FIRST && itemtype <= ITEM_TF2C_W_LAST) + { + AddEntityString(ent, std::string(tf2c_weapon_names[itemtype - ITEM_TF2C_W_FIRST]) + " Spawner"); + if (CE_BYTE(ent, netvar.bRespawning)) + AddEntityString(ent, tf2c_spawner_respawn_str); + } + // Halloween spell esp + else if (item_spellbooks && (itemtype == ITEM_SPELL || itemtype == ITEM_SPELL_RARE)) + { + if (itemtype == ITEM_SPELL) + { + AddEntityString(ent, spell_str, colors::green); + } + else + { + AddEntityString(ent, rare_spell_str, colors::FromRGBA8(139, 31, 221, 255)); + } + } + // Crumpkin esp https://wiki.teamfortress.com/wiki/Halloween_pumpkin + else if (item_crumpkin && itemtype == ITEM_CRUMPKIN) + { + AddEntityString(ent, crumpkin_str, colors::FromRGBA8(253, 203, 88, 255)); + } + } } - else if (classid == CL_CLASS(CCurrencyPack) && item_money) + // MVM Money esp + if (classid == CL_CLASS(CCurrencyPack) && item_money) { if (CE_BYTE(ent, netvar.bDistributed)) { @@ -1132,71 +1270,8 @@ void _FASTCALL ProcessEntity(CachedEntity *ent) { AddEntityString(ent, mvm_money_str); } - - // Other item esp - } - else if (itemtype != ITEM_NONE && item_esp) - { - - // Health pack esp - if (item_health_packs && (itemtype >= ITEM_HEALTH_SMALL && itemtype <= ITEM_HEALTH_LARGE || itemtype == ITEM_HL_BATTERY)) - { - if (itemtype == ITEM_HEALTH_SMALL) - AddEntityString(ent, health_small_str); - if (itemtype == ITEM_HEALTH_MEDIUM) - AddEntityString(ent, health_medium_str); - if (itemtype == ITEM_HEALTH_LARGE) - AddEntityString(ent, health_big_str); - if (itemtype == ITEM_HL_BATTERY) - AddEntityString(ent, hl_battery_str); - - // TF2C Adrenaline esp - } - else if (item_adrenaline && itemtype == ITEM_TF2C_PILL) - { - AddEntityString(ent, pill_str); - - // Ammo pack esp - } - else if (item_ammo_packs && itemtype >= ITEM_AMMO_SMALL && itemtype <= ITEM_AMMO_LARGE) - { - if (itemtype == ITEM_AMMO_SMALL) - AddEntityString(ent, ammo_small_str); - if (itemtype == ITEM_AMMO_MEDIUM) - AddEntityString(ent, ammo_medium_str); - if (itemtype == ITEM_AMMO_LARGE) - AddEntityString(ent, ammo_big_str); - - // Powerup esp - } - else if (item_powerups && itemtype >= ITEM_POWERUP_FIRST && itemtype <= ITEM_POWERUP_LAST) - { - AddEntityString(ent, std::string(powerups[itemtype - ITEM_POWERUP_FIRST])); //User should already know it's a pickup - - // TF2C weapon spawner esp - } - else if (item_weapon_spawners && itemtype >= ITEM_TF2C_W_FIRST && itemtype <= ITEM_TF2C_W_LAST) - { - AddEntityString(ent, std::string(tf2c_weapon_names[itemtype - ITEM_TF2C_W_FIRST]) + " SPAWNER"); - if (CE_BYTE(ent, netvar.bRespawning)) - AddEntityString(ent, tf2c_spawner_respawn_str); - - // Halloween spell esp - } - else if (item_spellbooks && (itemtype == ITEM_SPELL || itemtype == ITEM_SPELL_RARE)) - { - if (itemtype == ITEM_SPELL) - { - AddEntityString(ent, spell_str, colors::green); - } - else - { - AddEntityString(ent, rare_spell_str, colors::FromRGBA8(139, 31, 221, 255)); - } - } - - // Building esp } + // Building esp else if (ent->m_Type() == ENTITY_BUILDING && buildings) { diff --git a/src/hacks/Misc.cpp b/src/hacks/Misc.cpp index 4a259e07..9c65662e 100644 --- a/src/hacks/Misc.cpp +++ b/src/hacks/Misc.cpp @@ -776,6 +776,14 @@ static InitRoutine init([]() { // Patch! patch_scoreboardcolor1->Patch(); patch_scoreboardcolor2->Patch(); + + EC::Register( + EC::LevelInit, + []() { + // Remove truce status + setTruce(false); + }, + "truce_reset"); }); } // namespace ScoreboardColoring diff --git a/src/helpers.cpp b/src/helpers.cpp index 3c908572..730ef5b7 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -963,7 +963,7 @@ bool AmbassadorCanHeadshot() } static std::random_device random_device; -static std::mt19937 engine{random_device()}; +static std::mt19937 engine{ random_device() }; float RandFloatRange(float min, float max) { @@ -1930,3 +1930,13 @@ bool HookNetvar(std::vector path, ProxyFnHook &hook, RecvVarProxyFn } return false; } + +static bool is_truce_active = false; +bool isTruce() +{ + return is_truce_active; +} +void setTruce(bool status) +{ + is_truce_active = status; +} diff --git a/src/hooks/DispatchUserMessage.cpp b/src/hooks/DispatchUserMessage.cpp index 3d4fedc2..5b75cf53 100644 --- a/src/hooks/DispatchUserMessage.cpp +++ b/src/hooks/DispatchUserMessage.cpp @@ -120,6 +120,22 @@ DEFINE_HOOKED_METHOD(DispatchUserMessage, bool, void *this_, int type, bf_read & buf.Seek(0); break; } + // Hud message + case 26: + { + // Hud message type + auto message_type = buf.ReadByte(); + + // Truce activated + if (message_type == 26) + setTruce(true); + // Truce deactivated + else if (message_type == 27) + setTruce(false); + + buf.Seek(0); + break; + } case 12: if (hacks::shared::catbot::anti_motd && hacks::shared::catbot::catbotmode) { diff --git a/src/itemtypes.cpp b/src/itemtypes.cpp index 2880918b..d29b5653 100644 --- a/src/itemtypes.cpp +++ b/src/itemtypes.cpp @@ -34,6 +34,8 @@ ItemManager::ItemManager() : mapper() RegisterModelMapping("models/items/ammopack_small_bday.mdl", ITEM_AMMO_SMALL); RegisterModelMapping("models/items/ammopack_medium_bday.mdl", ITEM_AMMO_MEDIUM); RegisterModelMapping("models/items/ammopack_large_bday.mdl", ITEM_AMMO_LARGE); + // Crumpkin + RegisterModelMapping("models/props_halloween/pumpkin_loot.mdl", ITEM_CRUMPKIN); // == POWERUPS RegisterModelMapping("models/pickups/pickup_powerup_haste.mdl", ITEM_POWERUP_HASTE); @@ -71,7 +73,17 @@ ItemManager::ItemManager() : mapper() RegisterModelMapping("models/props_halloween/hwn_spellbook_upright_major.mdl", ITEM_SPELL_RARE); RegisterModelMapping("models/items/crystal_ball_pickup_major.mdl", ITEM_SPELL_RARE); - RegisterSpecialMapping([](CachedEntity *ent) -> bool { return ent->m_iClassID() == CL_CLASS(CTFAmmoPack); }, ITEM_AMMO_MEDIUM); + // == GHOSTS + RegisterModelMapping("models/props_halloween/ghost.mdl", HALLOWEEN_GHOST); + RegisterModelMapping("models/props_halloween/ghost_no_hat_red.mdl", HALLOWEEN_GHOST_NOHAT_RED); + RegisterModelMapping("models/props_halloween/ghost_no_hat.mdl", HALLOWEEN_GHOST_NOHAT); + + // == BOMBS + RegisterModelMapping("models/props_laughter/balloonbomb.mdl", BOMB_BALLOONBOMB); + RegisterModelMapping("models/props_coast/wooden_barrel.mdl", BOMB_WOODENBARREL); + RegisterModelMapping("models/props_invasion/props_alien/walker_explode.mdl", BOMB_WALKEREXPLODE); + + RegisterSpecialMapping([](CachedEntity *ent) -> bool { return ent->m_iClassID() == CL_CLASS(CTFAmmoPack) && g_ItemManager.mapper.GetItemType(ent) != ITEM_CRUMPKIN; }, ITEM_AMMO_MEDIUM); RegisterModelMapping("models/items/medkit_overheal.mdl", ITEM_TF2C_PILL); // TF2C spawners