diff --git a/LANGUAGE.Balthazar b/LANGUAGE.Balthazar index 9430f5f..ce4c3be 100644 --- a/LANGUAGE.Balthazar +++ b/LANGUAGE.Balthazar @@ -146,6 +146,10 @@ BALTHAZAR_ARMORGIVE_UPGRADE_1 = "WE LOVE UPGRADES!"; BALTHAZAR_ARMORGIVE_UPGRADE_2 = "BETTER IS GOOD!"; BALTHAZAR_ARMORGIVE_UPGRADE_3 = "STRONG!"; +BALTHAZAR_ARMORGIVE_WORNOVER_1 = "ANOTHER ONE!"; +BALTHAZAR_ARMORGIVE_WORNOVER_2 = "MORE BETTER!"; +BALTHAZAR_ARMORGIVE_WORNOVER_3 = "EVEN MORE!"; + BALTHAZAR_ARMORGIVE_BETTERDURABILITY_1 = "MUCH BETTER!"; BALTHAZAR_ARMORGIVE_BETTERDURABILITY_2 = "WE LIKE THAT!"; BALTHAZAR_ARMORGIVE_BETTERDURABILITY_3 = "AH YES!"; diff --git a/LANGUAGE.Daina b/LANGUAGE.Daina index 8349636..caa13de 100644 --- a/LANGUAGE.Daina +++ b/LANGUAGE.Daina @@ -218,6 +218,10 @@ DAINA_ARMORGIVE_UPGRADE_1 = "I needed that upgrade. Thank you."; DAINA_ARMORGIVE_UPGRADE_2 = "Wonderful!"; DAINA_ARMORGIVE_UPGRADE_3 = "Awesome."; +DAINA_ARMORGIVE_WORNOVER_1 = "Thanks, this will go great with the rest of my outfit."; +DAINA_ARMORGIVE_WORNOVER_2 = "Ooh, another one!"; +DAINA_ARMORGIVE_WORNOVER_3 = "This gives me more chances for flair! Thanks."; + DAINA_ARMORGIVE_BETTERDURABILITY_1 = "Thanks, this will last much longer than my old armor."; DAINA_ARMORGIVE_BETTERDURABILITY_2 = "Much better!"; DAINA_ARMORGIVE_BETTERDURABILITY_3 = "This gives me a much better sense of security. Thanks."; diff --git a/LANGUAGE.Freylis b/LANGUAGE.Freylis index f005a70..436fb28 100644 --- a/LANGUAGE.Freylis +++ b/LANGUAGE.Freylis @@ -148,6 +148,10 @@ FREYLIS_ARMORGIVE_UPGRADE_1 = "Thank you, this one is much better."; FREYLIS_ARMORGIVE_UPGRADE_2 = "I really appreciate your concern for my well-being."; FREYLIS_ARMORGIVE_UPGRADE_3 = "Great stuff. Thanks."; +FREYLIS_ARMORGIVE_WORNOVER_1 = "I hope it comes with more pocket space."; +FREYLIS_ARMORGIVE_WORNOVER_2 = "I'm just glad it fits."; +FREYLIS_ARMORGIVE_WORNOVER_3 = "Another one couldn't hurt."; + FREYLIS_ARMORGIVE_BETTERDURABILITY_1 = "Better than the old one, that's for sure."; FREYLIS_ARMORGIVE_BETTERDURABILITY_2 = "Has fewer dents than the old one."; FREYLIS_ARMORGIVE_BETTERDURABILITY_3 = "Definitely sturdier than what I have."; diff --git a/LANGUAGE.Nari b/LANGUAGE.Nari index a71af63..2620d4a 100644 --- a/LANGUAGE.Nari +++ b/LANGUAGE.Nari @@ -142,6 +142,10 @@ NARI_ARMORGIVE_UPGRADE_1 = "I needed that upgrade. Thank you."; NARI_ARMORGIVE_UPGRADE_2 = "Wonderful!"; NARI_ARMORGIVE_UPGRADE_3 = "Awesome."; +NARI_ARMORGIVE_WORNOVER_1 = "Thanks, this will go great with the rest of my outfit."; +NARI_ARMORGIVE_WORNOVER_2 = "Ooh, another one!"; +NARI_ARMORGIVE_WORNOVER_3 = "This gives me more chances for flair! Thanks."; + NARI_ARMORGIVE_BETTERDURABILITY_1 = "Thanks, this will last much longer than my old armor."; NARI_ARMORGIVE_BETTERDURABILITY_2 = "Much better!"; NARI_ARMORGIVE_BETTERDURABILITY_3 = "This gives me a much better sense of security. Thanks."; diff --git a/LANGUAGE.RecruitedMarine b/LANGUAGE.RecruitedMarine index 8202c50..0541464 100644 --- a/LANGUAGE.RecruitedMarine +++ b/LANGUAGE.RecruitedMarine @@ -138,6 +138,10 @@ MARINE_ARMORGIVE_UPGRADE_1 = "Thank you, commander."; MARINE_ARMORGIVE_UPGRADE_2 = "Awesome."; MARINE_ARMORGIVE_UPGRADE_3 = "Good stuff, commander."; +MARINE_ARMORGIVE_WORNOVER_1 = "I'll put it to good use, commander."; +MARINE_ARMORGIVE_WORNOVER_2 = "Does it come with more pockets, commander?"; +MARINE_ARMORGIVE_WORNOVER_3 = "Another layer of protection."; + MARINE_ARMORGIVE_BETTERDURABILITY_1 = "Much obliged, commander."; MARINE_ARMORGIVE_BETTERDURABILITY_2 = "Bless you, commander."; MARINE_ARMORGIVE_BETTERDURABILITY_3 = "This will last much longer."; diff --git a/LANGUAGE.Sewie b/LANGUAGE.Sewie index 56f6a6a..9648b0c 100644 --- a/LANGUAGE.Sewie +++ b/LANGUAGE.Sewie @@ -146,6 +146,10 @@ SEWIE_ARMORGIVE_UPGRADE_1 = "I needed that upgrade. Thank you."; SEWIE_ARMORGIVE_UPGRADE_2 = "Wonderful!"; SEWIE_ARMORGIVE_UPGRADE_3 = "Awesome."; +SEWIE_ARMORGIVE_WORNOVER_1 = "Thanks, this will go great with the rest of my outfit."; +SEWIE_ARMORGIVE_WORNOVER_2 = "Ooh, another one!"; +SEWIE_ARMORGIVE_WORNOVER_3 = "This gives me more chances for flair! Thanks."; + SEWIE_ARMORGIVE_BETTERDURABILITY_1 = "Thanks, this will last much longer than my old armor."; SEWIE_ARMORGIVE_BETTERDURABILITY_2 = "Much better!"; SEWIE_ARMORGIVE_BETTERDURABILITY_3 = "This gives me a much better sense of security. Thanks."; diff --git a/README.md b/README.md index 4c4738d..5725f53 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Hideous Destructor Followers _Originally made by Accensus, now maintained by the community._ +_Requires [HDCoreLib](https://github.com/HDest-Community/hdest-core-lib)._ **NOTE: *Freylis's sprites are not for public use. Please do not use them anywhere. Thank you.*** @@ -131,4 +132,4 @@ Sounds: > ### Known Issues > --- > - Sometimes followers will fail to follow the player or other followers while in specific sectors even if nothing obvious is blocking their way. This primarily happens on older maps that use the REJECT lump for sight checking. I don't know of a possible fix without side effects that I could implement on the mod's side. -> \ No newline at end of file +> diff --git a/zscript/AI.zsc b/zscript/AI.zsc index 35f0c31..2e8f6a6 100644 --- a/zscript/AI.zsc +++ b/zscript/AI.zsc @@ -69,12 +69,11 @@ extend class HDFollower SetStateLabel('StapleOwnAss'); } - if (Status <= FStatus_WaitingForWeapon) - //if (Status >= FStatus_WaitingForWearable && Status <= FStatus_WaitingForWeapon) + if (Status >= FStatus_WaitingForWearable && Status <= FStatus_WaitingForWeapon) { switch (Status) { - //case FStatus_WaitingForWearable: LookForWearable(); break; + case FStatus_WaitingForWearable: LookForWearable(); break; case FStatus_WaitingForWeapon: LookForWeapon(); break; } A_Face(LinkedPlayer, 15); diff --git a/zscript/CommandMenu.zsc b/zscript/CommandMenu.zsc index 0013f55..10abad2 100644 --- a/zscript/CommandMenu.zsc +++ b/zscript/CommandMenu.zsc @@ -915,23 +915,45 @@ extend class FollowerHandler sb.Fill(col, pos.x, pos.y, size.x, size.y, flags); sb.Fill(Color(DarkAlpha, 0, 0, 0), pos.x + 1, pos.y + 1, size.x - 2, size.y - 2, flags); - if (wearable is 'HDWeapon') + if (wearable is 'HDStorageItem') { + if (!(Level.time % TICRATE)) HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Drawing HDStorageItem Wearable: '"..wearable.getClassName().."'..."); + sb.DrawImage(""..wearable.Icon, pos + size / 2, flags | sb.DI_ITEM_CENTER, box: size - (3, 3)); - sb.DrawString(fnt, sb.FormatNumber(HDWeapon(wearable).GetSBarNum(), 1, 4), pos + size - (4, 10), flags | sb.DI_TEXT_ALIGN_RIGHT, sb.SavedColour); + sb.DrawString(fnt, "\c[Olive]"..sb.FormatNumber(HDStorageItem(wearable).GetSBarNum(), 1, 4), pos + size - (4, 10), flags | sb.DI_TEXT_ALIGN_RIGHT); } - - if (wearable is 'HDArmourWorn') + else if (wearable is 'HDWeapon') { - sb.DrawImage(HDArmourWorn(wearable).mega?"ARMCA0":"ARMSA0", pos + size / 2, flags | sb.DI_ITEM_CENTER, box: size - (3, 3)); - sb.DrawString(fnt, (HDArmourWorn(wearable).Mega ? "\c[Blue]" : "\c[DarkGreen]")..HDArmourWorn(wearable).Durability, pos + size - (4, 10), flags | sb.DI_TEXT_ALIGN_RIGHT); + if (!(Level.time % TICRATE)) HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Drawing HDWeapon Wearable: '"..wearable.getClassName().."'..."); + + sb.DrawImage(""..wearable.Icon, pos + size / 2, flags | sb.DI_ITEM_CENTER, box: size - (3, 3)); + sb.DrawString(fnt, sb.FormatNumber(HDWeapon(wearable).GetSBarNum(), 1, 4), pos + size - (4, 10), flags | sb.DI_TEXT_ALIGN_RIGHT, sb.SavedColour); } + else if (wearable is 'HDArmourWorn') + { + if (!(Level.time % TICRATE)) HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Drawing HDArmourWorn Wearable: '"..wearable.getClassName().."'..."); - if (wearable is 'HDMagicShield') + if (HDArmourWorn(wearable).bDROPTRANSLATION) { + sb.DrawImage(""..HDArmourWorn(wearable).armoursprite, pos + size / 2, flags | sb.DI_ITEM_CENTER | sb.DI_TRANSLATABLE, box: size - (3, 3), translation: wearable.owner.translation); + } else { + sb.DrawImage(""..HDArmourWorn(wearable).armoursprite, pos + size / 2, flags | sb.DI_ITEM_CENTER, box: size - (3, 3)); + } + sb.DrawString(fnt, "\c[White]"..HDArmourWorn(wearable).durability, pos + size - (4, 10), flags | sb.DI_TEXT_ALIGN_RIGHT); + } + else if (wearable is 'HDMagicShield') { + if (!(Level.time % TICRATE)) HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Drawing HDMagicShield Wearable: '"..wearable.getClassName().."'..."); + sb.DrawImage(""..wearable.Icon, pos + size / 2, flags | sb.DI_ITEM_CENTER, box: size - (3, 3)); sb.DrawString(fnt, "\c[Cyan]"..HDMagicShield(wearable).amount, pos + size - (4, 10), flags | sb.DI_TEXT_ALIGN_RIGHT); } + else + { + if (!(Level.time % TICRATE)) HDCore.log("Follower."..getClassName(), LOGGING_WARN, "Attempting to Draw Unknown Wearable: '"..wearable.getClassName().."'..."); + + sb.DrawImage(""..wearable.Icon, pos + size / 2, flags | sb.DI_ITEM_CENTER, box: size - (3, 3)); + sb.DrawString(fnt, "\c[DarkGray]"..wearable.amount, pos + size - (4, 10), flags | sb.DI_TEXT_ALIGN_RIGHT); + } } private ui void DrawRectangle(HDStatusBar sb, vector2 pos, vector2 size, Color col, HUDFont fnt, string command, int flags, int textCol = Font.CR_WHITE) @@ -1798,11 +1820,10 @@ extend class FollowerHandler if (cmd.IndexOf("hdf_wearablecommand") != -1) { - - static const Name worldItemClasses[] = { 'HDArmour', 'PortableRadsuit', 'HDBackpack', 'HDPersonalShieldGenerator', 'ShieldCore' }; - static const Name wornItemClasses[] = { 'HDArmourWorn', 'WornRadsuit', 'HDBackpack', 'HDPersonalShieldGenerator', 'HDMagicShield' }; - static const string languagePrefixex[] = { "ARMORGIVE", "RADSUITGIVE", "BACKPACKGIVE", "PSGGIVE", "SHIELDCOREGIVE" }; - static const string soundPrefixes[] = { "ArmorGive", "RadsuitGive", "BackpackGive", "PSGGive", "ShieldCoreGive" }; + static const Name worldItemClasses[] = { 'HDArmour', 'PortableRadsuit', 'HDStorageItem', 'HDPersonalShieldGenerator', 'ShieldCore' }; + static const Name wornItemClasses[] = { 'HDArmourWorn', 'WornRadsuit', 'HDStorageItem', 'HDPersonalShieldGenerator', 'HDMagicShield' }; + static const string languagePrefixex[] = { "ARMORGIVE", "RADSUITGIVE", "BACKPACKGIVE", "PSGGIVE", "SHIELDCOREGIVE" }; + static const string soundPrefixes[] = { "ArmorGive", "RadsuitGive", "BackpackGive", "PSGGive", "ShieldCoreGive" }; lastFol.WearableInfo.WorldItemCls = worldItemClasses[e.Args[0]]; lastFol.WearableInfo.WornItemCls = wornItemClasses[e.Args[0]]; diff --git a/zscript/Data.zsc b/zscript/Data.zsc index b8f294b..c4c39c4 100644 --- a/zscript/Data.zsc +++ b/zscript/Data.zsc @@ -48,12 +48,14 @@ class FollowerData play int SuturesLeft; + name ArmorCls; int ArmorDurability; - bool ArmorMega; bool HasRadsuit; - ItemStorage Storage; + name StorageCls; + Array StorageContents; + int StorageBulk; Array WeaponData; Array ShieldData; @@ -141,19 +143,21 @@ extend class HDFollower data.SuturesLeft = SuturesLeft; - let armor = HDArmourWorn(FindInventory("HDArmourWorn")); + let armor = HDArmourWorn(FindInventory('HDArmourWorn', true)); if (armor) { - data.ArmorDurability = Armor.Durability; - data.ArmorMega = Armor.Mega; + data.ArmorCls = armor.GetClassName(); + data.ArmorDurability = armor.Durability; } data.HasRadsuit = FindInventory('WornRadsuit') != null; - let bpack = HDBackpack(FindInventory('HDBackpack')); + let bpack = HDStorageItem(FindInventory('HDStorageItem', true)); if (bpack) { - data.Storage = bpack.Storage; + data.StorageCls = bpack.GetClassName(); + data.StorageContents.copy(bpack.items); + data.StorageBulk = bpack.weaponBulk(); } for (Inventory next = Inv; next != null; next = Next.Inv) @@ -167,7 +171,7 @@ extend class HDFollower { wepData.WeaponStatus[i] = wpn.WeaponStatus[i]; } - Console.Printf(wpn.GetClassName()); + // Console.Printf(wpn.GetClassName()); data.WeaponData.Push(wepData); } @@ -225,7 +229,7 @@ class FollowerBody : HDPickup abstract double total = 0; for (int i = 0; i < Data.Size(); ++i) { - total += default.Bulk + (Data[i].Storage != null ? 100 + Data[i].Storage.TotalBulk * 0.7 : 0); + total += default.Bulk + Data[i].StorageBulk; } return total; } @@ -254,25 +258,19 @@ class FollowerBody : HDPickup abstract { FollowerData data = invoker.Data[invoker.Data.Size() - 1]; + bool forced = invoker.FromIncap || HDCore.isPreSpawn(); bool ReturnValue = false; for (int i = 0; i < 100; ++i) { Actor a; bool success; int Distance = random(20, 48); - int RandAngle = invoker.FromIncap || level.time < 2 ? random(0, 359) : 0; + int RandAngle = forced ? random(0, 359) : 0; vector3 dest = Vec3Angle(Distance, angle + RandAngle); - Sector sec = level.PointInSector(dest.xy); - if (sec && pos.z - sec.NextLowestFloorAt(dest.x, dest.y, dest.z) > GetDefaultByType(data.FollowerClass).MaxStepHeight || !level.IsPointInLevel(dest)) + Sector sec = Level.PointInSector(dest.xy); + if (sec && pos.z - sec.NextLowestFloorAt(dest.x, dest.y, dest.z) > GetDefaultByType(data.FollowerClass).MaxStepHeight || !Level.IsPointInLevel(dest)) { - if (invoker.FromIncap || level.time < 2) - { - continue; - } - else - { - break; - } + if (forced) continue; else break; } [success, a] = A_SpawnItemEx(data.FollowerClass, Distance, 0, random(8, 16), angle: RandAngle); @@ -320,9 +318,9 @@ class FollowerBody : HDPickup abstract if (data.ArmorDurability > 0) { - let armor = HDArmourWorn(fol.GiveInventoryType('HDArmourWorn')); + let armor = HDArmourWorn(fol.GiveInventoryType(data.ArmorCls)); armor.Durability = data.ArmorDurability; - armor.Mega = data.ArmorMega; + // armor.Mega = data.ArmorMega; } if (data.HasRadsuit) @@ -331,10 +329,11 @@ class FollowerBody : HDPickup abstract fol.GiveInventoryType('PortableRadsuit'); } - if (data.Storage != null) + if (data.StorageCls != 'None') { - let bpack = HDBackpack(fol.GiveInventoryType('HDBackpack')); - bpack.Storage = data.Storage; + let bpack = HDStorageItem(fol.GiveInventoryType(data.StorageCls)); + bpack.items.copy(data.StorageContents); + bpack.RecalculateBulk(); } for (int j = 0; j < data.WeaponData.Size(); ++j) diff --git a/zscript/FollowerHandler.zsc b/zscript/FollowerHandler.zsc index 942a33e..27cc139 100644 --- a/zscript/FollowerHandler.zsc +++ b/zscript/FollowerHandler.zsc @@ -88,7 +88,7 @@ class FollowerHandler : EventHandler while (Followers.Size() > 0) { HDFollower flw = Followers[0]; - if (flw.IsDeadOrMissing()) + if (!flw || flw.IsDeadOrMissing()) { RemoveFollower(flw, true); } diff --git a/zscript/Loadout.zsc b/zscript/Loadout.zsc index 03589eb..bd2baf6 100644 --- a/zscript/Loadout.zsc +++ b/zscript/Loadout.zsc @@ -14,25 +14,21 @@ extend class HDFollower for (int i = 0; i < lines.Size(); ++i) { - int amt = lines[i].Mid(3).ToInt(); - if (amt == 0) - { - amt = 1; - } - string ref = lines[i].Left(3); + int amt = max(1, lines[i].Mid(3).ToInt()); - class cls = HDBackpack.FindByRefId(ref); - if (!cls) - { - Continue; - } + class cls = HDHandlers.ParseRefID(lines[i].Left(3)); + if (!cls) Continue; - if (cls is 'GarrisonArmour' || cls is 'GarrisonArmourWorn' || cls is 'BattleArmour' || cls is 'BattleArmourWorn') + if (cls is 'HDArmour') { - bool mega = cls == 'BattleArmour' || cls == 'BattleArmourWorn'; - GiveArmour(1.0, mega ? 1.0 : 0, amt); + HDF.Give(self, cls); + UseInventory(FindInventory(cls)); continue; } + else if (cls is 'HDArmourWorn') + { + HDF.Give(self, cls); + } if (cls is 'HDWeapon' && !GetDefaultByType((class)(cls)).bWIMPY_WEAPON) { @@ -68,10 +64,10 @@ extend class HDFollower } else { - if (cls is 'HDBackpack') + if (cls is 'HDStorageItem') { - let bp = HDBackpack(GiveInventoryType('HDBackpack')); - bp.LoadoutConfigure(input.Mid(input.IndexOf("bak") + 3)); + let bp = HDStorageItem(GiveInventoryType(cls)); + bp.LoadoutConfigure(input.Mid(input.IndexOf(lines[i].Left(3)) + 3)); } else if (cls is 'PortableRadsuit') { diff --git a/zscript/Management.zsc b/zscript/Management.zsc index 86b52f6..53bb89c 100644 --- a/zscript/Management.zsc +++ b/zscript/Management.zsc @@ -65,18 +65,21 @@ extend class FollowerHandler void RemoveFollower(HDFollower flw, bool permanent = false, bool noDestroy = false) { - int Index = Followers.Find(flw); - if (Index != Followers.Size()) + if (flw) { - if (permanent && flw.MissingClass && players[Net_Arbitrator].mo) + int Index = Followers.Find(flw); + if (Index != Followers.Size()) { - players[Net_Arbitrator].mo.A_GiveInventory(flw.MissingClass); - } - if (!noDestroy) - { - flw.Destroy(); + if (permanent && flw.MissingClass && players[Net_Arbitrator].mo) + { + players[Net_Arbitrator].mo.A_GiveInventory(flw.MissingClass); + } + if (!noDestroy) + { + flw.Destroy(); + } + Followers.Delete(Index); } - Followers.Delete(Index); } } diff --git a/zscript/Medical.zsc b/zscript/Medical.zsc index 56c9130..e3638e6 100644 --- a/zscript/Medical.zsc +++ b/zscript/Medical.zsc @@ -14,6 +14,8 @@ extend class HDFollower protected void StopHealing() { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Stopping Healing..."); + ClearGoal(); Status = FStatus_None; Order = PrevOrder; @@ -22,16 +24,24 @@ extend class HDFollower protected void HealSelf(int amt, int flags = HSF_ALL) { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Healing Self..."); + if (flags & HSF_HEALTH) { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Giving Health."); + GiveBody(amt); } if (flags & HSF_BODYDAMAGE) { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Removing Body Damage."); + BodyDamage = max(0, BodyDamage - amt); } if (flags & HSF_BLOOD) { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Refilling Blood."); + Bloodloss = max(0, Bloodloss - amt); } } @@ -75,6 +85,8 @@ extend class HDFollower protected bool TryUnwrapMedikit() { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Attempting to unwrap Medikit..."); + if (GetAmount('PortableMedikit') > 0) { // Give/Drop Stimpack @@ -201,6 +213,8 @@ extend class HDFollower if (LinkedPlayer.incaptimer > MinIncap) { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Helping up player..."); + A_Face(LinkedPlayer); if (!random(0, 4)) { @@ -214,6 +228,8 @@ extend class HDFollower #### JK 5; #### L 5 { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Assessing H. Dumpty..."); + // If player is too far or is ordered to stop, stop. if (DistanceToPlayer > HDCONST_ONEMETRE * 1.2 || Order != FOrder_ComeAndHelp) { @@ -269,6 +285,8 @@ extend class HDFollower } #### LLLLL 3 { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Assessing H. Dumpty, part 2..."); + if (DistanceToPlayer > HDCONST_ONEMETRE * 1.2 || Order != FOrder_ComeAndHelp) { StopHealing(); @@ -290,6 +308,8 @@ extend class HDFollower PatchUpEnd: #### J 10 { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Assessing H. Dumpty, part 3..."); + SuturesLeft--; PatchPlayerWounds(1); } @@ -299,6 +319,8 @@ extend class HDFollower #### A 10; #### A 5 { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Assessing self..."); + if (!CanHealSelf() || Order != FOrder_HealSelf) { StopHealing(); @@ -319,6 +341,8 @@ extend class HDFollower } #### GGGGG 3 { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Assessing self, part 2..."); + if (Order != FOrder_HealSelf) { StopHealing(); @@ -332,6 +356,8 @@ extend class HDFollower PatchUpSelfEnd: #### A 10 { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Assessing self, part 3..."); + HealSelf(10, HSF_HEALTH | HSF_BODYDAMAGE); SuturesLeft--; } @@ -341,6 +367,7 @@ extend class HDFollower #### J 25 A_Face(LinkedPlayer); #### J 20 { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Apply second blood..."); // if(patient)invoker.weaponstatus[SBS_INJECTCOUNTER]++;else{ // invoker.weaponstatus[SBS_INJECTCOUNTER]=0; // return; @@ -360,6 +387,8 @@ extend class HDFollower #### J 25 A_Face(LinkedPlayer); #### J 20 { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Apply stim..."); + A_Face(LinkedPlayer); LinkedPlayer.A_SetBlend("7a 3a 18", 0.1, 4); LinkedPlayer.A_SetPitch(pitch + 2, SPF_INTERPOLATE); @@ -381,6 +410,7 @@ extend class HDFollower #### J 25 A_Face(LinkedPlayer); #### J 20 { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Apply second flesh..."); PatchPlayerBurns(1); } diff --git a/zscript/Messages.zsc b/zscript/Messages.zsc index 6b502f5..e1323b3 100644 --- a/zscript/Messages.zsc +++ b/zscript/Messages.zsc @@ -41,7 +41,7 @@ extend class HDFollower private void ResetCommentTimer() { - CommentTimer = random(35 * 15, 35 * 50); + CommentTimer = random(TICRATE * 15, TICRATE * 50); } protected void PlayIdleComment() diff --git a/zscript/Recruitment.zsc b/zscript/Recruitment.zsc index e5bcbfa..41bbc6c 100644 --- a/zscript/Recruitment.zsc +++ b/zscript/Recruitment.zsc @@ -117,9 +117,8 @@ extend class FollowerHandler let Armor = HDArmourWorn(m.FindInventory('HDArmourWorn')); if (Armor) { - let NewArmor = HDArmourWorn(recruit.GiveInventoryType('HDArmourWorn')); + let NewArmor = HDArmourWorn(recruit.GiveInventoryType(Armor.GetClassName())); NewArmor.Durability = Armor.Durability; - NewArmor.Mega = Armor.Mega; } if (m.InStateSequence(m.CurState, m.FindState('Falldown'))) diff --git a/zscript/Wearables.zsc b/zscript/Wearables.zsc index b15d190..5ff85a6 100644 --- a/zscript/Wearables.zsc +++ b/zscript/Wearables.zsc @@ -23,8 +23,12 @@ extend class HDFollower private void LookForWearable() { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Looking For Wearable..."); + if (!WearableInfo.GetWorldItem() || !WearableInfo.GetWornItem()) { + HDCore.log("Follower."..getClassName(), LOGGING_WARN, "Invalid WorldItem or WornItem."); + return; } @@ -36,31 +40,82 @@ extend class HDFollower return; } - CheckProximity(WearableInfo.worldItemCls, radius + MaxSearchRange, 1, CPXF_CLOSEST | CPXF_SETTRACER); + CheckProximity(WearableInfo.worldItemCls, radius + MaxSearchRange, 1, CPXF_ANCESTOR|CPXF_CLOSEST|CPXF_SETTRACER); let foundWearable = Inventory(tracer); - let wornWearable = FindInventory(WearableInfo.WornItemCls); + let wornWearable = FindInventory(WearableInfo.WornItemCls, true); if (foundWearable) { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Found Wearable: '"..foundWearable.getClassName().."'"); + + let ha = HDArmour(foundWearable); + let hm = HDMagAmmo(foundWearable); + + int haWornLayer; + + if (ha) { + let haWornCls = (Class)(ha.wornName()); + let haWornDefs = GetDefaultByType(haWornCls); + haWornLayer = HDArmourWorn(haWornDefs).wornlayer; + } + if (!wornWearable) { PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_NONE"), WearableInfo.SoundPrefix.."/None", PMType_General); } - else if (WearableInfo.GetWornItem() is 'HDArmourWorn') + else if (HDCore.isChildClass(wornWearable.getClass(), 'HDMagicShield')) + { + if (wornWearable.amount < hm.mags[hm.mags.size() - 1]) + { + PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_BETTERDURABILITY"), WearableInfo.SoundPrefix.."/BetterDurability", PMType_General); + } + else + { + PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_NOTHANKS"), WearableInfo.SoundPrefix.."/NoThanks", PMType_Important); + Status = FStatus_None; + tracer = null; + return; + } + } + else if (HDCore.isChildClass(wornWearable.getClass(), 'HDArmourWorn')) { - let foundArmor = HDArmour(foundWearable); - let wornArmor = HDArmourWorn(wornWearable); + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Wearing Armor: '"..wornWearable.getClassName().."'"); - // [Ace] 1030 because mega armor's durability is calculated as 1000 + actual durability. Only while on the ground, though. - if (!wornArmor.Mega && foundArmor.Mega && foundArmor.Mags[0] >= 1020 || wornArmor.Mega && wornArmor.Durability < 20 && !foundArmor.Mega && foundArmor.Mags[0] > 60) + // Loop through all possible instances of HDArmourWorn, + // in case the order in which they're in the Follower's inventory + // causes HHelmet to be selected first before any others, + // invalidating the checks below + HDArmourWorn wearableSameWornLayer; + HDArmourWorn wearableHighestLayer; + for (let i = inv; i; i = i.inv) { - PrintMessage(GetResponse("ARMORGIVE_UPGRADE"), "ArmorGive/Upgrade", PMType_General); + if (HDCore.isChildClass(i.getClass(), 'HDArmourWorn')) + { + let w = HDArmourWorn(i); + + if (w.wornLayer > 0) + { + if (w.wornLayer == haWornLayer) wearableSameWornLayer = w; + + if (!wearableHighestLayer || w.wornLayer > wearableHighestLayer.wornLayer) wearableHighestLayer = w; + } + } + + if (wearableSameWornLayer && wearableHighestLayer) break; } - else if (foundArmor.Mega == wornArmor.Mega && wornArmor.Durability < foundArmor.Mags[0] % 1000) + + if (wearableSameWornLayer) HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Wearing '"..wearableSameWornLayer.getClassName().."' on same layer ("..wearableSameWornLayer.wornlayer..")..."); + if (wearableHighestLayer) HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Wearing '"..wearableHighestLayer.getClassName().."' at outermost layer ("..wearableHighestLayer.wornlayer..")..."); + + if (wearableHighestLayer && haWornLayer > wearableHighestLayer.wornLayer) { - PrintMessage(GetResponse("ARMORGIVE_BETTERDURABILITY"), "ArmorGive/BetterDurability", PMType_General); + PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_WORNOVER"), WearableInfo.SoundPrefix.."/WornOver", PMType_General); } - else + else if (wearableSameWornLayer && ((1.0 * wearableSameWornLayer.Durability) / wearableSameWornLayer.default.Durability) < ((1.0 * ha.Mags[ha.Mags.Size() - 1]) / ha.maxperunit)) + { + PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_BETTERDURABILITY"), WearableInfo.SoundPrefix.."/BetterDurability", PMType_General); + } + else if (ha.wornLayer > 0) { PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_NOTHANKS"), WearableInfo.SoundPrefix.."/NoThanks", PMType_Important); Status = FStatus_None; @@ -76,146 +131,105 @@ extend class HDFollower return; } - //while (HDPlayerPawn.CheckStrip(self, foundWearable) != CSResult_Nothing); - while (HDPlayerPawn.CheckStrip(self, foundWearable)); - - if (HDWeapon(foundWearable)) - { - HDWeapon(foundWearable).ActualPickup(self); - } - else if (HDPickup(foundWearable)) - { - HDPickup(foundWearable).ActualPickup(self); - UseInventory(FindInventory(foundWearable.GetClass())); - } - Status = FStatus_None; - } - tracer = null; - } - - void TryUseWearable() - { - if (Status == FStatus_InactiveOrDead || !WearableInfo.GetWorldItem() || !WearableInfo.GetWornItem()) - { - return; - } - - if (Status == FStatus_WaitingForWearable) - { - CheckProximity('HDArmour', radius + 24, 1, CPXF_CLOSEST | CPXF_SETTRACER); - let FoundArmor = HDArmour(tracer); - let WornArmor = HDArmourWorn(FindInventory('HDArmourWorn')); + let hw = HDWeapon(foundWearable); + let hp = HDPickup(foundWearable); - CheckProximity('HDBackpack', radius + 24, 1, CPXF_CLOSEST | CPXF_SETTRACER); - let FoundBackpack = HDBackpack(tracer); - let WornBackpack = HDBackpack(FindInventory('HDBackpack')); + if ((ha && haWornLayer > 0) || (hp && hp.wornlayer > 0) || (hw && hw.wornlayer > 0)) { + let tempWornLayer = ha ? ha.wornLayer : 1; - CheckProximity('Shieldcore', radius + 24, 1, CPXF_CLOSEST | CPXF_SETTRACER); - let FoundShield = Shieldcore(tracer); - let WornShield = HDMagicShield(FindInventory('HDMagicShield')); + if (ha && haWornLayer != tempWornLayer) ha.wornLayer = haWornLayer; - if (FoundArmor) - { - string ATag = GetTag(); - if (WornArmor) - { - // [Ace] 1030 because mega armor's durability is calculated as 1000 + actual durability. Only while on the ground, though. - if (!WornArmor.Mega && FoundArmor.Mega && FoundArmor.Mags[0] >= 1030 || WornArmor.Mega && WornArmor.Durability < 20 && !FoundArmor.Mega && FoundArmor.Mags[0] > 60) - { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_UPGRADE"), WearableInfo.SoundPrefix.."/Upgrade", PMType_General); - } - else if (FoundArmor.Mega == WornArmor.Mega && WornArmor.Durability < FoundArmor.Mags[0] % 1000) - { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_BETTERDURABILITY"), WearableInfo.SoundPrefix.."/BetterDurability", PMType_General); - } - else - { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_NOTHANKS"), WearableInfo.SoundPrefix.."/NoThanks", PMType_Important); - Status = FStatus_None; - tracer = null; - return; - } - - A_DropInventory(WornArmor.GetClass()); - } - else - { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_NONE"), WearableInfo.SoundPrefix.."/None", PMType_General); - } + while (!HDPlayerPawn.CheckStrip(self, foundWearable)) HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Stripping Wearable."); - FoundArmor.ActualPickup(self); - UseInventory(FindInventory("HDArmour")); - Status = FStatus_None; - return; + if (ha) ha.wornLayer = tempWornLayer; } - else if (FoundBackpack) + + if (hw) { - string BTag = GetTag(); - if (WornBackpack) - { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_CANCEL"), WearableInfo.SoundPrefix.."/Cancel", PMType_Important); - } - else - { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_NONE"), WearableInfo.SoundPrefix.."/None", PMType_General); - } - - FoundBackpack.ActualPickup(self); - Status = FStatus_None; - return; + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Giving HDWeapon Wearable."); + hw.ActualPickup(self); } - else if (FoundShield) + else if (hm) { - string STag = GetTag(); - if (WornShield) + if (HDCore.isChildClass(hm.getClass(), 'ShieldCore')) { - if (FoundShield.amount > WornShield.amount) - { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_BETTERDURABILITY"), WearableInfo.SoundPrefix.."/BetterDurability", PMType_General); - - A_DropInventory(WornShield.GetClass()); - } - else + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Giving ShieldCore."); + + HDF.Give(self, "HDMagicShield"); + let sss = HDPickup(FindInventory("HDMagicShield")); + if (sss) { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_NOTHANKS"), WearableInfo.SoundPrefix.."/NoThanks", PMType_Important); - Status = FStatus_None; - tracer = null; - return; + sss.amount = 1; + sss.maxamount = hm.mags[hm.mags.size() - 1]; + sss.bulk = hm.magBulk; + sss.mass = sss.maxAmount - 1; + sss.bQUICKTORETALIATE = false; + + if (sss.amount > 0) HDMagicShield.FlashSparks(self); } + + hm.destroy(); } - else + else if (HDCore.isChildClass(hm.getClass(), 'HDArmour')) { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_NONE"), WearableInfo.SoundPrefix.."/None", PMType_General); - } + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Giving HDArmour Wearable."); - A_GiveInventory("HDMagicShield"); - let sss = HDPickup(FindInventory("HDMagicShield")); - if (sss) - { - sss.amount = 1; - sss.maxamount = FoundShield.mags[FoundShield.mags.size() - 1]; - sss.bulk = FoundShield.magBulk; - sss.mass = FoundShield.amount - 1; + let wornName = HDArmour(hm).wornName(); + HDF.Give(self, wornName); + let worn = HDArmourWorn(FindInventory(wornName)); + worn.Durability = hm.mags[hm.mags.size() - 1]; - if (sss.amount > 0) HDMagicShield.FlashSparks(self); + hm.destroy(); } + else + { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Giving HDMagAmmo Wearable."); - FoundShield.destroy(); - Status = FStatus_None; - return; + let cls = hm.getClass(); + hm.ActualPickup(self); + if (!UseInventory(FindInventory(cls))) HDCore.log("Follower."..getClassName(), LOGGING_WARN, "Failed to wear '"..(hm ? hm.getClassName() : cls.getClassName()).."'."); + } } - else + else if (hp) { - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_CANCEL"), WearableInfo.SoundPrefix.."/Cancel", PMType_Important); - } + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Giving HDPickup Wearble."); - tracer = null; + let cls = hm.getClass(); + hp.ActualPickup(self); + if (!UseInventory(FindInventory(cls))) HDCore.log("Follower."..getClassName(), LOGGING_WARN, "Failed to wear '"..(hm ? hm.getClassName() : cls.getClassName()).."'."); + } Status = FStatus_None; + } + tracer = null; + } + + void TryUseWearable() + { + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Trying to use Wearable..."); + + if (!WearableInfo.GetWorldItem() || !WearableInfo.GetWornItem()) + { + HDCore.log("Follower."..getClassName(), LOGGING_WARN, "Invalid WorldItem or WornItem."); return; } - Status = FStatus_WaitingForWearable; - PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_INIT"), WearableInfo.SoundPrefix.."/Init", PMType_Important); + switch (Status) { + case FStatus_InactiveOrDead: + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Can't use, am ded."); + break; + case FStatus_WaitingForWearable: + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Cancelling waiting for Wearable..."); + + PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_CANCEL"), WearableInfo.SoundPrefix.."/Cancel", PMType_Important); + Status = FStatus_None; + break; + default: + HDCore.log("Follower."..getClassName(), LOGGING_DEBUG, "Going to wait for Wearable..."); + + Status = FStatus_WaitingForWearable; + PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_INIT"), WearableInfo.SoundPrefix.."/Init", PMType_Important); + break; + } } void DropWearable() @@ -225,10 +239,10 @@ extend class HDFollower return; } - let wornItem = FindInventory(WearableInfo.WornItemCls); + let wornItem = FindInventory(WearableInfo.WornItemCls, true); if (wornItem) { - A_DropInventory(WearableInfo.WornItemCls); + A_DropInventory(wornItem.getClass()); PrintMessage(GetResponse(WearableInfo.LanguagePrefix.."_STRIP"), WearableInfo.SoundPrefix.."/Strip", PMType_General); Status = FStatus_None; }