diff --git a/README.md b/README.md index 28a18294..784ca06c 100644 --- a/README.md +++ b/README.md @@ -224,8 +224,6 @@ ConVar: `sc_ft <0 or 1>` | `INSTANCE_ITEMS` | Instances pickup items and weapons for each player. Instanced items disappear once picked up and 'respawn' along with the player. | | `INSTANCE_ITEMS_NORESET` | If enabled, items will not 'respawn' picked up items after death. | | `KEEP_EQUIPMENT` | Makes players spawn with previously picked up equipment (suit, weapons). Global for all players. | -| `STRIP_DEFAULT_EQUIPMENT` | Removes default multiplayer equipment. | -| `STRIP_DEFAULT_EQUIPMENT_KEEPSUIT` | | | `DISABLE_CANISTER_DROPS` | Disables item drops when players die in multiplayer. | | `NO_TELEFRAGGING` | Prevents teleporting props and players from slaying other players. | | `NOBLOCK` | Prevents player-on-player collisions. (This feature requires `mp_teamplay 1` to fix smoothness issues.) | diff --git a/edt/common/base/coop_base.edt b/edt/common/base/coop_base.edt index 34651639..f0ef4e78 100644 --- a/edt/common/base/coop_base.edt +++ b/edt/common/base/coop_base.edt @@ -11,8 +11,6 @@ "HEV_SOUNDS" "1" "INSTANCE_ITEMS" "0" "INSTANCE_ITEMS_NORESET" "0" - "STRIP_DEFAULT_EQUIPMENT" "0" - "STRIP_DEFAULT_EQUIPMENT_KEEPSUIT" "0" "DISABLE_CANISTER_DROPS" "0" "AUTODETECT_MAP_END" "1" "CHANGELEVEL_FX" "1" @@ -53,6 +51,11 @@ "sv_always_run" "~S 1" } + "equipment" + { + "defaults" "1" + } + "entity_base_coop" { } diff --git a/edt/common/base/coop_base_sp_conversion.edt b/edt/common/base/coop_base_sp_conversion.edt index 0880b9be..27b896ea 100644 --- a/edt/common/base/coop_base_sp_conversion.edt +++ b/edt/common/base/coop_base_sp_conversion.edt @@ -5,19 +5,21 @@ "config" { "intro_type" "freeze" + "features" { "INSTANCE_ITEMS" "1" - "STRIP_DEFAULT_EQUIPMENT" "1" "DISABLE_CANISTER_DROPS" "1" "SP_WEAPONS" "1" } + "console" { "mp_falldamage" "1" "bm_multiplayer_fall_protection" "1" "sv_mp_spawneffect_item" "0" } + "define" { "outputs_fixup_player_in_target" "1" @@ -33,6 +35,12 @@ "never_close_areaportals" "1" "fix_reload_triggers" "1" } + + "equipment" + { + "defaults" "0" + } + "entity_base_sp_conversion" { // remove globalnames - prevents entities not spawning due to the map transition system not being in place diff --git a/gamedata/srccoop.games.txt b/gamedata/srccoop.games.txt index 2a8eea27..86a44dc9 100644 --- a/gamedata/srccoop.games.txt +++ b/gamedata/srccoop.games.txt @@ -810,6 +810,13 @@ } } } + "*Player::GiveDefaultItems" + { + "signature" "*Player::GiveDefaultItems" + "callconv" "thiscall" + "return" "void" + "this" "entity" + } "CRecipientFilter::IgnorePredictionCull" { "signature" "CRecipientFilter::IgnorePredictionCull" @@ -980,6 +987,11 @@ "windows" "\x55\x8B\xEC\x83\xEC\x50\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\x2A\x53\x8B\x5D\x2A\xB8\xFF\xFF\x00\x00" "linux" "@_ZN14AI_CriteriaSet14AppendCriteriaEPKcS1_f" } + "*Player::GiveDefaultItems" + { + "windows" "\x53\x56\x57\x8B\xF9\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01\x8B\x80\x88\x00\x00\x00" + "linux" "@_ZN16CBlackMesaPlayer16GiveDefaultItemsEv" + } "CRecipientFilter::IgnorePredictionCull" { "windows" "\x8A\x41\x1D" @@ -1430,6 +1442,11 @@ "windows" "\x55\x8B\xEC\x83\xEC\x48\x53\x56\x8B\x75\x08\xBB\xFF\xFF\x00\x00\x57\x8B\xF9\x66\x89\x5D" "linux" "@_ZN14AI_CriteriaSet14AppendCriteriaEPKcS1_f" } + "*Player::GiveDefaultItems" + { + "windows" "\x56\x57\x8B\xF9\x6A\x01\x8B\x07" + "linux" "@_ZN13CHL2MP_Player16GiveDefaultItemsEv" + } } // _ _ _ ___ __ __ _____ __ __ ______ __ __ _____ _______ _____ _ _ ______ _____ diff --git a/scripting/include/srccoop/checkpoint.inc b/scripting/include/srccoop/checkpoint.inc index 649c85f5..39eb6375 100644 --- a/scripting/include/srccoop/checkpoint.inc +++ b/scripting/include/srccoop/checkpoint.inc @@ -470,6 +470,7 @@ enum struct CCoopSpawnSystemData CCoopEquipment m_pDefaultEquipment; // holds map's equipment configuration bool m_bOrdered; // whether checkpoints are specified in order of progression bool m_bRespawnOnLogicAutosave; // use logic_autosave for survival respawns + bool m_bDefaultGameEquipment; // allow equipping of game's default items } CCoopSpawnSystemData g_pSpawnSystemData; @@ -490,6 +491,7 @@ methodmap CCoopSpawnSystem data.m_iCurrentCheckpoint = -1; data.m_iSpawnAtCheckpoint = -1; data.m_pDefaultEquipment.Clear(); + data.m_bDefaultGameEquipment = false; CCoopSpawnEntry pEntry; for (int i = 0; i < data.m_pCheckpointList.Length; i++) @@ -666,21 +668,8 @@ methodmap CCoopSpawnSystem return false; } - public static void StripPlayer(CBasePlayer pPlayer) - { - if (CoopManager.IsFeatureEnabled(FT_STRIP_DEFAULT_EQUIPMENT)) - { - pPlayer.RemoveAllItems(!CoopManager.IsFeatureEnabled(FT_STRIP_DEFAULT_EQUIPMENT_KEEPSUIT)); - } - } - public static void SpawnPlayerEquipment(CBasePlayer pPlayer) { - #if !defined SRCCOOP_BLACKMESA - // bm uses game_player_equip - CCoopSpawnSystem.StripPlayer(pPlayer); - #endif - CCoopEquipment pSavedEquipment; if (data.m_iCurrentCheckpoint == 0 && EquipmentManager.GetEquipment(pPlayer, pSavedEquipment)) { @@ -936,7 +925,19 @@ methodmap CCoopSpawnSystem } else if (strcmp(szKey, "item", false) == 0) { - data.m_pDefaultEquipment.AddItem(szValue); + CCoopSpawnSystem.AddSpawnItem(szValue, true); + } + else if (strcmp(szKey, "defaults", false) == 0) + { + data.m_bDefaultGameEquipment = !!StringToInt(szValue); + + #if defined SRCCOOP_BLACKMESA + // to simulate classic multiplayer, we need the suit added + if (data.m_bDefaultGameEquipment) + { + CCoopSpawnSystem.AddSpawnItem("item_suit"); + } + #endif } else { diff --git a/scripting/include/srccoop/features.inc b/scripting/include/srccoop/features.inc index 1ab14501..3a1fab04 100644 --- a/scripting/include/srccoop/features.inc +++ b/scripting/include/srccoop/features.inc @@ -16,8 +16,8 @@ enum SourceCoopFeature FT_NOBLOCK = (1 << 5), FT_SHOW_WELCOME_MESSAGE = (1 << 6), FT_HEV_SOUNDS = (1 << 7), - FT_STRIP_DEFAULT_EQUIPMENT = (1 << 8), - FT_STRIP_DEFAULT_EQUIPMENT_KEEPSUIT = (1 << 9), + //Free = (1 << 8), + //Free = (1 << 9), FT_DISABLE_CANISTER_DROPS = (1 << 10), FT_AUTODETECT_MAP_END = (1 << 11), FT_CHANGELEVEL_FX = (1 << 12), @@ -38,8 +38,6 @@ methodmap FeatureMap < StringMap pMap.SetValue("NOBLOCK", FT_NOBLOCK); pMap.SetValue("SHOW_WELCOME_MESSAGE", FT_SHOW_WELCOME_MESSAGE); pMap.SetValue("HEV_SOUNDS", FT_HEV_SOUNDS); - pMap.SetValue("STRIP_DEFAULT_EQUIPMENT", FT_STRIP_DEFAULT_EQUIPMENT); - pMap.SetValue("STRIP_DEFAULT_EQUIPMENT_KEEPSUIT", FT_STRIP_DEFAULT_EQUIPMENT_KEEPSUIT); pMap.SetValue("DISABLE_CANISTER_DROPS", FT_DISABLE_CANISTER_DROPS); pMap.SetValue("AUTODETECT_MAP_END", FT_AUTODETECT_MAP_END); pMap.SetValue("CHANGELEVEL_FX", FT_CHANGELEVEL_FX); diff --git a/scripting/include/srccoop/globals.inc b/scripting/include/srccoop/globals.inc index faa18d13..492f20c7 100644 --- a/scripting/include/srccoop/globals.inc +++ b/scripting/include/srccoop/globals.inc @@ -49,6 +49,7 @@ DynamicHook hkThink; DynamicHook hkUpdateOnRemove; DynamicHook hkEvent_Killed; DynamicHook hkKeyValue_char; +DynamicDetour hkGiveDefaultItems; #if defined GAMEPATCH_ALLOW_FLASHLIGHT DynamicHook hkFAllowFlashlight; diff --git a/scripting/include/srccoop/playerpatch.inc b/scripting/include/srccoop/playerpatch.inc index d08695f5..962d93b0 100644 --- a/scripting/include/srccoop/playerpatch.inc +++ b/scripting/include/srccoop/playerpatch.inc @@ -15,6 +15,18 @@ public MRESReturn Hook_FAllowFlashlight(Handle hReturn, Handle hParams) return MRES_Supercede; } +//------------------------------------------------------ +// Default spawn items +//------------------------------------------------------ +public MRESReturn Hook_GiveDefaultItems(int _this) +{ + if (CoopManager.IsCoopModeEnabled() && !g_pSpawnSystemData.m_bDefaultGameEquipment) + { + return MRES_Supercede; + } + return MRES_Ignored; +} + //------------------------------------------------------ // The singleplayer override for PreThink handles our // prop pickup, sprinting, vm anims, suit queue updates, etc diff --git a/scripting/srccoop.sp b/scripting/srccoop.sp index 0e0d92e7..cfc7cbb1 100644 --- a/scripting/srccoop.sp +++ b/scripting/srccoop.sp @@ -61,6 +61,7 @@ void LoadGameData() LoadDHookVirtual(pGameConfig, hkUpdateOnRemove, "CBaseEntity::UpdateOnRemove"); LoadDHookVirtual(pGameConfig, hkEvent_Killed, "CBaseEntity::Event_Killed"); LoadDHookVirtual(pGameConfig, hkKeyValue_char, "CBaseEntity::KeyValue_char"); + LoadDHookDetour(pGameConfig, hkGiveDefaultItems, "*Player::GiveDefaultItems", Hook_GiveDefaultItems); #if defined ENTPATCH_RELATION_TYPE LoadDHookVirtual(pGameConfig, hkIRelationType, "CBaseCombatCharacter::IRelationType"); @@ -381,19 +382,6 @@ public void OnConfigsExecutedPost() #if defined SRCCOOP_BLACKMESA - if (CoopManager.IsFeatureEnabled(FT_STRIP_DEFAULT_EQUIPMENT)) - { - CBaseEntity pGameEquip = CBaseEntity.Create("game_player_equip"); // will spawn players with nothing if it exists - if (pGameEquip.IsValid()) - { - if (!CoopManager.IsFeatureEnabled(FT_STRIP_DEFAULT_EQUIPMENT_KEEPSUIT)) - { - pGameEquip.SetSpawnFlags(SF_PLAYER_EQUIP_STRIP_SUIT); - } - pGameEquip.Spawn(); - } - } - if (CoopManager.IsFeatureEnabled(FT_DISABLE_CANISTER_DROPS)) { CBaseEntity pGameGamerules = CBaseEntity.Create("game_mp_gamerules");