From c27a10e0f83991922b677732047a8e1439ffd339 Mon Sep 17 00:00:00 2001 From: skittles1 Date: Tue, 3 Mar 2015 04:26:14 +0800 Subject: [PATCH] Misc attack related fixes. -Fixed Bramble Wall starting hit points (were being spawned with 0HP). -Fixed Bramble Wall damage threshold messages. -Stop thrasher spin attacks hitting phased/spectating players. -Fix a bug causing thrasher spin attacks to overwrite the damage to be done to each target with the value returned from the previous target. -Changed thrasher spin attacks to use high precision damage numbers. -Survival arena now checks for invalid targets before calling TargetSwitch. -Added IsOwnedByPlayer message in Monster. Returns TRUE if the monster (or its master) is owned by a player, FALSE otherwise. Checks for apparitions and monster evil twins in addition to true minions. -Added minion checks to the aggro code in survival arenas, to stop player minions being aggroed on players. -Fixed bug causing new mobs to not aggro properly if a boss or miniboss is present. -Lowered solo aggro to 20% of mobs spawned. -When one participant is left in guild survival, or on every kill in solo, try to aggro another mob on the player. -Fixed grammar error (her/his vs he/she) in phased out cast resource. -Add a check for phase/spectator to CheckPlayerAttack in Spell. -Formatting fixes in AttackSpell (no code change). -Add phase/spectator check for Earthquake and radius projectile targeting. -Add immortal and phase/spectator check to Heat's damage effect. -Add utility message (CreateSpellBook) to create a spell book for monsters to use. Creates a one-spell spellbook only; good for testing. -Add stats to keep track of highest level reached in each of the arenas. -Add system message to get survival status report easier. --- .../holder/nomoveon/battler/monster.kod | 57 +++++ .../nomoveon/battler/monster/BRAMBLE.kod | 8 +- .../nomoveon/battler/monster/thrasher.kod | 15 +- .../active/holder/nomoveon/battler/player.kod | 19 +- .../holder/room/monsroom/survivalroom.kod | 226 ++++++++++++++---- kod/object/passive/spell.kod | 6 +- kod/object/passive/spell/atakspel.kod | 20 +- .../passive/spell/atakspel/earthqua.kod | 7 + kod/object/passive/spell/atakspel/radproj.kod | 7 + kod/object/passive/spell/roomench/heat.kod | 25 +- kod/util.kod | 6 + kod/util/statistics.kod | 39 ++- kod/util/survivalmaint.kod | 28 ++- kod/util/system.kod | 10 + 14 files changed, 390 insertions(+), 83 deletions(-) diff --git a/kod/object/active/holder/nomoveon/battler/monster.kod b/kod/object/active/holder/nomoveon/battler/monster.kod index 247548ccc7..98706f63f6 100644 --- a/kod/object/active/holder/nomoveon/battler/monster.kod +++ b/kod/object/active/holder/nomoveon/battler/monster.kod @@ -6109,6 +6109,63 @@ messages: return; } + IsOwnedByPlayer() + "Checks the three cases of minions, and returns TRUE if owned by " + "a player, FALSE if not. If minion has a monster for a master, " + "IsOwnedByPlayer is called on the master." + { + if poMaster <> $ + { + if IsClass(poMaster,&Player) + { + return TRUE; + } + + if IsClass(poMaster,&Monster) + { + return Send(poMaster,@IsOwnedByPlayer); + } + + % Could be a room or an item that owns the monster. + % If we allow players to attach minions to guild halls + % or other creative uses of non-player/monster owners, + % we may need to change this. + return FALSE; + } + + if poApparitionCaster <> $ + { + if IsClass(poApparitionCaster,&Player) + { + return TRUE; + } + + if IsClass(poApparitionCaster,&Monster) + { + return Send(poApparitionCaster,@IsOwnedByPlayer); + } + + return FALSE; + } + + if poEvilTwinCaster <> $ + { + if IsClass(poEvilTwinCaster,&Player) + { + return TRUE; + } + + if IsClass(poEvilTwinCaster,&Monster) + { + return Send(poEvilTwinCaster,@IsOwnedByPlayer); + } + + return FALSE; + } + + return FALSE; + } + % This section deals with minion code. CommandMinionAttack(oMaster=$,oTarget=$) { diff --git a/kod/object/active/holder/nomoveon/battler/monster/BRAMBLE.kod b/kod/object/active/holder/nomoveon/battler/monster/BRAMBLE.kod index 327aae1873..021ee52048 100644 --- a/kod/object/active/holder/nomoveon/battler/monster/BRAMBLE.kod +++ b/kod/object/active/holder/nomoveon/battler/monster/BRAMBLE.kod @@ -128,7 +128,7 @@ messages: Constructed() { - piHit_points = piBrambleHits; + piHit_points = piBrambleHits * 100; piMax_hit_points = piBrambleHits; propagate; @@ -272,21 +272,21 @@ messages: return; } - if iDamage < 3 + if iDamage <= 200 { Send(what,@MsgSendUser,#message_rsc=Brambles_damage2); return; } - if iDamage = 3 + if iDamage <= 300 { Send(what,@MsgSendUser,#message_rsc=Brambles_damage3); return; } - if iDamage = 4 + if iDamage <= 400 { Send(what,@MsgSendUser,#message_rsc=Brambles_damage4); diff --git a/kod/object/active/holder/nomoveon/battler/monster/thrasher.kod b/kod/object/active/holder/nomoveon/battler/monster/thrasher.kod index 792c6fea57..569232749c 100644 --- a/kod/object/active/holder/nomoveon/battler/monster/thrasher.kod +++ b/kod/object/active/holder/nomoveon/battler/monster/thrasher.kod @@ -17,8 +17,10 @@ constants: PALSY_CHANCE = 20 - SPIN_DAMAGE_MIN = 7 - SPIN_DAMAGE_MAX = 15 + % These are high precision damage amounts, with two 'decimal places'. + % Actual damage shown to player will be (default) 7-15. + SPIN_DAMAGE_MIN = 700 + SPIN_DAMAGE_MAX = 1500 resources: @@ -344,12 +346,13 @@ messages: each_obj = Send(oRoom,@HolderExtractObject,#data=i); if IsClass(each_obj,&User) AND Send(self,@CanReach,#what=each_obj) + AND (NOT Send(each_obj,@IsInCannotInteractMode)) { lValidTargets = Cons(each_obj,lValidTargets); } } - return lValidTargets; + return lValidTargets; } DoSpinAttack(lFinalTargets=$) @@ -367,9 +370,9 @@ messages: for i in lTargets { - iDamage = Send(i,@AssessDamage,#what=self,#damage=iDamage, - #atype=viAttack_type,#aspell=viAttack_spell); - if iDamage = $ + if Send(i,@AssessDamage,#what=self,#damage=iDamage, + #atype=viAttack_type,#aspell=viAttack_spell, + #precision=TRUE) = $ { Send(self,@KilledSomething,#what=i,#use_weapon=self); } diff --git a/kod/object/active/holder/nomoveon/battler/player.kod b/kod/object/active/holder/nomoveon/battler/player.kod index cda5bd604a..a977697e01 100644 --- a/kod/object/active/holder/nomoveon/battler/player.kod +++ b/kod/object/active/holder/nomoveon/battler/player.kod @@ -5239,8 +5239,12 @@ messages: origdamage = damage/100; color_rsc = player_hit_color_none; - % Attacks against a minion master will cause minions to defend the master - Send(self,@CommandMinionAttack,#oMaster=self,#oTarget=what); + % Attacks against a minion master will cause minions to defend the master. + if what <> $ + AND IsClass(what,&Battler) + { + Send(self,@CommandMinionAttack,#oMaster=self,#oTarget=what); + } if what <> $ AND IsClass(what,&monster) { @@ -5275,7 +5279,8 @@ messages: #caster=Nth(i,3),#resistance=iResistance); } - damage = Send(self,@GetDamageFromResistance,#what=damage,#value=iResistance); + damage = Send(self,@GetDamageFromResistance,#what=damage, + #value=iResistance); % Allow protective spells a chance to improve when they take effect! for i in plPassiveImprovement @@ -5391,12 +5396,14 @@ messages: if piHealth <= 0 { if stroke_obj = $ - OR NOT Send(stroke_obj,@PlayerWasKilledMsg,#who=self,#attacker=what,#damage=$) + OR NOT Send(stroke_obj,@PlayerWasKilledMsg,#who=self, + #attacker=what,#damage=$) { if report { - Send(self,@MsgSendUser,#message_rsc=Send(self,@PlayerWasHit,#atype=atype,#aspell=aspell), - #parm1=color_rsc,#parm2=Send(what,@GetCapDef),#parm3=Send(what,@GetName)); + Send(self,@MsgSendUser,#message_rsc=Send(self,@PlayerWasHit, + #atype=atype,#aspell=aspell),#parm1=color_rsc, + #parm2=Send(what,@GetCapDef),#parm3=Send(what,@GetName)); } } diff --git a/kod/object/active/holder/room/monsroom/survivalroom.kod b/kod/object/active/holder/room/monsroom/survivalroom.kod index 8f77ba7983..3727b16f46 100644 --- a/kod/object/active/holder/room/monsroom/survivalroom.kod +++ b/kod/object/active/holder/room/monsroom/survivalroom.kod @@ -816,11 +816,12 @@ messages: propagate; } - % Minions! - if IsClass(victim,&Monster) - AND (Send(victim,@GetMaster) <> $ + % Minions! Keep these checks instead of using IsOwnedByPlayer + % as we don't want monster minions to count either. + if (IsClass(victim,&Monster) + AND Send(victim,@GetMaster) <> $) OR IsClass(victim,&Brambles) - OR Send(victim,@IsIllusion)) + OR Send(victim,@IsIllusion) { propagate; } @@ -937,23 +938,30 @@ messages: plLevelGoals = DelListElem(plLevelGoals,i); } - - % Finish it up if only one guy remains in a public room. - if piPublic - AND plParticipants <> $ + + if plParticipants <> $ AND Length(plParticipants) = 1 { - for mob in plActive + % Finish it up if only one guy remains in a public room. + if piPublic { - oMonster = First(mob); - if IsClass(oMonster,&Monster) - AND Send(oMonster,@GetMaster) = $ + for mob in plActive { - oTarget = First(plParticipants); - Send(oMonster,@TargetSwitch,#what=oTarget,#iHatred=100); - Send(oMonster,@EnterStateChase,#target=oTarget,#actnow=True); + oMonster = First(mob); + if IsClass(oMonster,&Monster) + AND (NOT Send(oMonster,@IsOwnedByPlayer)) + { + oTarget = First(plParticipants); + Send(oMonster,@TargetSwitch,#what=oTarget,#iHatred=100); + Send(oMonster,@EnterStateChase,#target=oTarget,#actnow=True); + } } } + else + { + % Aggro one mob on the player. + Send(self,@AggroOne,#who=(First(plParticipants))); + } } } @@ -980,7 +988,12 @@ messages: AggroBosses() { - local oTarget, i, n, each_obj; + local oTarget, i, n, each_obj, count; + + if plParticipants = $ + { + return; + } for i in plActive { @@ -990,7 +1003,28 @@ messages: { if GetClass(each_obj) = n { - oTarget = Nth(plParticipants,Random(1,Length(plParticipants))); + if Length(plParticipants) = 1 + { + oTarget = First(plParticipants); + } + else + { + oTarget = Nth(plParticipants,Random(1,Length(plParticipants))); + count = 0; + while (oTarget = $ + OR ((IsClass(oTarget,&DM) + AND Send(oTarget,@PlayerIsImmortal)) + OR Send(oTarget,@IsInCannotInteractMode))) + { + oTarget = Nth(plParticipants,Random(1,Length(plParticipants))); + count = count + 1; + if count > 10 + { + break; + } + } + } + Send(each_obj,@TargetSwitch,#what=oTarget,#iHatred=100); Send(each_obj,@EnterStateChase,#target=oTarget,#actnow=True); } @@ -1000,18 +1034,40 @@ messages: { if GetClass(each_obj) = n { - oTarget = Nth(plParticipants,Random(1,Length(plParticipants))); + if Length(plParticipants) = 1 + { + oTarget = First(plParticipants); + } + else + { + oTarget = Nth(plParticipants,Random(1,Length(plParticipants))); + count = 0; + while (oTarget = $ + OR ((IsClass(oTarget,&DM) + AND Send(oTarget,@PlayerIsImmortal)) + OR Send(oTarget,@IsInCannotInteractMode))) + { + oTarget = Nth(plParticipants,Random(1,Length(plParticipants))); + count = count + 1; + if count > 10 + { + break; + } + } + } + Send(each_obj,@TargetSwitch,#what=oTarget,#iHatred=100); Send(each_obj,@EnterStateChase,#target=oTarget,#actnow=True); } } } + return; } - + NewHoldObject(what=$) { - local oTarget, i; + local oTarget, i, count; if IsClass(what,&User) { @@ -1026,11 +1082,12 @@ messages: plParticipants = Cons(what,plParticipants); Send(self,@AggroSome,#who=what); + propagate; } } } - + if IsClass(what,&User) AND (piHasBegun AND piLevel > piLastJoinLevel) @@ -1044,12 +1101,10 @@ messages: if IsClass(what,&User) AND (NOT piHasBegun OR piLevel <= piLastJoinLevel) - { plParticipants = Cons(what,plParticipants); plLivesPerPlayer = Cons([what,3],plLivesPerPlayer); - if Length(plParticipants) = 1 AND NOT piPublic AND poGuildAssociation = $ @@ -1058,19 +1113,59 @@ messages: piLevel = Bound(piLevel,1,$); } Post(what,@MsgSendUser,#message_rsc=welcome_message); + propagate; } if IsClass(what,&Monster) AND plParticipants <> $ - AND plBosses <> $ - AND plMinibosses <> $ - AND FindListElem(plBosses,GetClass(what)) = 0 - AND FindListElem(plMinibosses,GetClass(what)) = 0 + AND (plBosses = $ + OR (plBosses <> $ + AND FindListElem(plBosses,GetClass(what)) = 0)) + AND (plMiniBosses = $ + OR (plMinibosses <> $ + AND FindListElem(plMinibosses,GetClass(what)) = 0)) + AND (NOT Send(what,@IsOwnedByPlayer)) { - oTarget = Nth(plParticipants,Random(1,Length(plParticipants))); - Post(what,@TargetSwitch,#what=oTarget,#iHatred=100); - Post(what,@EnterStateChase,#target=oTarget,#actnow=True); + if Length(plParticipants) = 1 + { + oTarget = First(plParticipants); + } + else + { + oTarget = Nth(plParticipants,Random(1,Length(plParticipants))); + count = 0; + while (oTarget = $ + OR ((IsClass(oTarget,&DM) + AND Send(oTarget,@PlayerIsImmortal)) + OR Send(oTarget,@IsInCannotInteractMode))) + { + oTarget = Nth(plParticipants,Random(1,Length(plParticipants))); + count = count + 1; + if count > 10 + { + break; + } + } + } + + if NOT piPublic + AND poGuildAssociation = $ + { + % Cut aggro to 1/5th in solo. + if Random(1,5) = 1 + { + Post(what,@TargetSwitch,#what=oTarget,#iHatred=100); + Post(what,@EnterStateChase,#target=oTarget, + #actnow=True); + } + } + else + { + % Public arenas get full aggro. + Post(what,@TargetSwitch,#what=oTarget,#iHatred=100); + Post(what,@EnterStateChase,#target=oTarget,#actnow=True); + } } if IsClass(what,&Monster) @@ -1081,35 +1176,73 @@ messages: propagate; } - + + AggroOne(who = $) + { + local i, iCount; + + if (IsClass(who,&DM) + AND Send(who,@PlayerIsImmortal)) + OR Send(who,@IsInCannotInteractMode) + { + return; + } + + iCount = 0; + + for i in plActive + { + if IsClass(First(i),&Monster) + AND (NOT Send(First(i),@IsOwnedByPlayer)) + AND Random(1,5) = 1 + { + Post(First(i),@TargetSwitch,#what=who,#iHatred=100); + Post(First(i),@EnterStateChase,#target=who,#actnow=True); + iCount = iCount + 1; + + if iCount >= 1 + { + return; + } + } + } + + return; + } + AggroSome(who=$) { local i, iCount; + if (IsClass(who,&DM) + AND Send(who,@PlayerIsImmortal)) + OR Send(who,@IsInCannotInteractMode) + { + return; + } + iCount = 0; - - if IsClass(who,&User) + + for i in plActive { - for i in plActive + if IsClass(First(i),&Monster) + AND (NOT Send(First(i),@IsOwnedByPlayer)) + AND Random(1,5) = 1 { - if IsClass(First(i),&Monster) - AND Random(1,5) = 1 + Post(First(i),@TargetSwitch,#what=who,#iHatred=100); + Post(First(i),@EnterStateChase,#target=who,#actnow=True); + iCount = iCount + 1; + + if iCount >= 5 { - Post(First(i),@TargetSwitch,#what=who,#iHatred=100); - Post(First(i),@EnterStateChase,#target=who,#actnow=True); - iCount = iCount + 1; - - if iCount >= 5 - { - return; - } + return; } } } - + return; } - + LeaveHold(what=$) { if IsClass(what,&User) @@ -1117,6 +1250,7 @@ messages: { Send(what,@DeactivateSpectatorMode); Post(self,@BootUser,#who=what); + propagate; } diff --git a/kod/object/passive/spell.kod b/kod/object/passive/spell.kod index cfd9548353..fa274b83d9 100644 --- a/kod/object/passive/spell.kod +++ b/kod/object/passive/spell.kod @@ -146,7 +146,8 @@ resources: Spell_too_few_hp_rsc = "You are not powerful enough to cast this spell." - cannot_cast_on_phased_out = "You can't cast anything on %s while %s is phased out of existence!" + cannot_cast_on_phased_out = \ + "You can't cast anything on %s while %s is phased out of existence!" classvars: @@ -780,7 +781,7 @@ messages: { Send(who,@MsgSendUser,#message_rsc=cannot_cast_on_phased_out, #parm1=Send(oTarget,@GetName), - #parm2=Send(oTarget,@GetHimHer)); + #parm2=Send(oTarget,@GetHeShe)); return FALSE; } @@ -1077,6 +1078,7 @@ messages: if i = who OR NOT IsClass(i,&Battler) OR (IsClass(i,&DM) AND Send(i,@PlayerIsImmortal)) + OR (IsClass(i,&Player) AND Send(i,@IsInCannotInteractMode)) OR (IsClass(i,&Monster) AND (Send(i,@GetBehavior) & AI_NPC)) OR Send(oRoom,@IsArena) diff --git a/kod/object/passive/spell/atakspel.kod b/kod/object/passive/spell/atakspel.kod index db733e13c9..7db3cad59d 100644 --- a/kod/object/passive/spell/atakspel.kod +++ b/kod/object/passive/spell/atakspel.kod @@ -236,14 +236,16 @@ messages: if IsClass(self,&Earthquake) { - iDamage = Send(self,@ComputeDamage,#who=who,#target=i,#iDamage=iDamage); + iDamage = Send(self,@ComputeDamage,#who=who,#target=i, + #iDamage=iDamage); if iDamage < 100 { % To prevent spam, we don't consider 0 damage earthquake hits. continue; } - iDamage = Send(i,@AssessDamage,#what=who,#damage=iDamage,#atype=viAttack_type, - #aspell=Send(self,@GetAttackSpell),#absolute=pbAbsolute,#precision=TRUE); + iDamage = Send(i,@AssessDamage,#what=who,#damage=iDamage, + #atype=viAttack_type,#aspell=Send(self,@GetAttackSpell), + #absolute=pbAbsolute,#precision=TRUE); if iDamage = $ { if IsClass(who,&Room) @@ -253,8 +255,9 @@ messages: } else { - Send(who,@MsgSendUser,#message_rsc=vrKilled_Someone,#parm1=Send(i,@GetDef), - #parm2=Send(i,@GetName),#parm3=Send(i,@GetHeShe)); + Send(who,@MsgSendUser,#message_rsc=vrKilled_Someone, + #parm1=Send(i,@GetDef),#parm2=Send(i,@GetName), + #parm3=Send(i,@GetHeShe)); } Send(i,@MsgSendUser,#message_rsc=vrKilled_Self); @@ -295,8 +298,8 @@ messages: local iDamage, iMysticism, iIntellect; % Get dual stats damage bonus. - % These difficult to master attack spells require both high mysticism and high intellect - % to reach their full potential. + % These difficult to master attack spells require both high mysticism + % and high intellect to reach their full potential. iMysticism = Send(who,@GetMysticism); iIntellect = Send(who,@GetIntellect); iDamage = ((100+bound(((iMysticism+iIntellect)/2)-25,0,40))*damage)/100; @@ -346,7 +349,8 @@ messages: else { Send(who,@MsgSendUser,#message_rsc=vrCast); - Send(who,@AssessHit,#what=who,#damage=iFinalDamage,#use_weapon=self); + Send(who,@AssessHit,#what=who,#damage=iFinalDamage, + #use_weapon=self); } } diff --git a/kod/object/passive/spell/atakspel/earthqua.kod b/kod/object/passive/spell/atakspel/earthqua.kod index f3fb866196..91fe541c0e 100644 --- a/kod/object/passive/spell/atakspel/earthqua.kod +++ b/kod/object/passive/spell/atakspel/earthqua.kod @@ -135,6 +135,13 @@ messages: AND Send(oRoom,@InFoyer,#who=each_obj) <> Send(oRoom,@InFoyer,#who=who)) { + % Skip players who are phased/in spectator mode. + if IsClass(each_obj,&Player) + AND Send(each_obj,@IsInCannotInteractMode) + { + continue; + } + lFinalTargets = Cons(each_obj,lFinalTargets); } } diff --git a/kod/object/passive/spell/atakspel/radproj.kod b/kod/object/passive/spell/atakspel/radproj.kod index f46491efe0..b04e1beb7d 100644 --- a/kod/object/passive/spell/atakspel/radproj.kod +++ b/kod/object/passive/spell/atakspel/radproj.kod @@ -75,6 +75,13 @@ messages: if each_obj <> who AND IsClass(each_obj,&Battler) { + % Skip players who are phased/in spectator mode. + if IsClass(each_obj,&Player) + AND Send(each_obj,@IsInCannotInteractMode) + { + continue; + } + iDistance = Send(who,@SquaredFineDistanceToLocation3D, #row=Send(each_obj,@GetRow), #col=Send(each_obj,@GetCol), diff --git a/kod/object/passive/spell/roomench/heat.kod b/kod/object/passive/spell/roomench/heat.kod index 1f54440df4..1ac49f880f 100644 --- a/kod/object/passive/spell/roomench/heat.kod +++ b/kod/object/passive/spell/roomench/heat.kod @@ -180,8 +180,21 @@ messages: { local oRoom, bDoDamage, iDamage, oArmor; + if who = $ + { + return; + } + + if ((IsClass(who,&DM) + AND Send(who,@PlayerIsImmortal)) + OR Send(who,@IsInCannotInteractMode)) + { + return; + } + bDoDamage = FALSE; - oArmor = send(who,@GetArmor); + + oArmor = Send(who,@GetArmor); oRoom = Send(who,@GetOwner); if oArmor <> $ @@ -191,14 +204,14 @@ messages: bDoDamage = TRUE; } - if send(oRoom,@CheckRoomFlag,#flag=ROOM_KILL_ZONE) + if Send(oRoom,@CheckRoomFlag,#flag=ROOM_KILL_ZONE) { bDoDamage = TRUE; } - if send(oRoom,@CheckRoomFlag,#flag=ROOM_SAFE_DEATH) + if Send(oRoom,@CheckRoomFlag,#flag=ROOM_SAFE_DEATH) { - if send(oRoom,@IsValidTarget,#who=who) + if Send(oRoom,@IsValidTarget,#who=who) { bDoDamage = TRUE; } @@ -211,7 +224,7 @@ messages: if bDoDamage { - iDamage = send(oArmor,@GetHeatDamage); + iDamage = Send(oArmor,@GetHeatDamage); % robes = no heat damage if iDamage = 0 @@ -261,7 +274,5 @@ messages: return; } - end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - diff --git a/kod/util.kod b/kod/util.kod index 27db2d8af4..1038e48852 100644 --- a/kod/util.kod +++ b/kod/util.kod @@ -575,5 +575,11 @@ messages: return retVal; } + CreateSpellBook(SID=SID_FIREBALL,mana=1) + "Creates a monster spellbook with a single spell." + { + return [[SID,mana,100]]; + } + end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/kod/util/statistics.kod b/kod/util/statistics.kod index 45b4bcf269..00cbcac025 100644 --- a/kod/util/statistics.kod +++ b/kod/util/statistics.kod @@ -43,14 +43,49 @@ properties: % Money Created this save period piMoneyCreated = 0 - % How many players have entered Survival Rooms? - piSurvivalRoomsEntered = 0 + % Highest level in a Survival Arenas + piPublicSurvivalLevel = 0 + piGuildSurvivalLevel = 0 + piSoloSurvivalLevel = 0 % How many ancient trinkets (stat reset tokens) have been found? piFoundTrinkets = 0 messages: + RecordPublicSurvivalLevel(iLevel=$) + { + if iLevel <> $ + AND iLevel > piPublicSurvivalLevel + { + piPublicSurvivalLevel = iLevel; + } + + return piPublicSurvivalLevel; + } + + RecordGuildSurvivalLevel(iLevel=$) + { + if iLevel <> $ + AND iLevel > piGuildSurvivalLevel + { + piGuildSurvivalLevel = iLevel; + } + + return piGuildSurvivalLevel; + } + + RecordSoloSurvivalLevel(iLevel=$) + { + if iLevel <> $ + AND iLevel > piSoloSurvivalLevel + { + piSoloSurvivalLevel = iLevel; + } + + return piSoloSurvivalLevel; + } + MoneyCreated(amount = 0) { piMoneyCreated = piMoneyCreated + amount; diff --git a/kod/util/survivalmaint.kod b/kod/util/survivalmaint.kod index a98c0d0a4f..968ff95df3 100644 --- a/kod/util/survivalmaint.kod +++ b/kod/util/survivalmaint.kod @@ -269,6 +269,22 @@ messages: { Send(i,@MsgSendUser,#message_rsc=public_ended, #parm1=Send(what,@GetLevel)); + % Keep track of highest level. + Send(Send(SYS,@GetStatistics),@RecordPublicSurvivalLevel, + #iLevel=Send(what,@GetLevel)); + } + } + else + { + if Send(what,@GetGuildAssociation) <> $ + { + Send(Send(SYS,@GetStatistics),@RecordGuildSurvivalLevel, + #iLevel=Send(what,@GetLevel)); + } + else + { + Send(Send(SYS,@GetStatistics),@RecordSoloSurvivalLevel, + #iLevel=Send(what,@GetLevel)); } } @@ -277,7 +293,7 @@ messages: return; } - + GetRegroupTime() { return piRegroupTime; @@ -347,7 +363,7 @@ messages: SurvivalStatusReport() { local i; - + if plSurvivalRooms = $ { Debug("No survival arenas active."); @@ -355,6 +371,14 @@ messages: return; } + % Report highest levels reached. + Debug("Highest Public Survival level reached is ", + Send(Send(SYS,@GetStatistics),@RecordPublicSurvivalLevel)); + Debug("Highest Guild Survival level reached is ", + Send(Send(SYS,@GetStatistics),@RecordGuildSurvivalLevel)); + Debug("Highest Solo Survival level reached is ", + Send(Send(SYS,@GetStatistics),@RecordSoloSurvivalLevel)); + for i in plSurvivalRooms { if Send(i,@GetPublicStatus) diff --git a/kod/util/system.kod b/kod/util/system.kod index e7fc140223..e4a744cf9f 100644 --- a/kod/util/system.kod +++ b/kod/util/system.kod @@ -4751,6 +4751,16 @@ messages: { return poSurvivalRoomMaintenance; } + + GetSurvivalReport() + { + if poSurvivalRoomMaintenance <> $ + { + return Send(poSurvivalRoomMaintenance,@SurvivalStatusReport); + } + + return $; + } RecreateTerritoryGame() {