-+-+-+-+-+-+-+-+ START OF PART 11 -+-+-+-+-+-+-+-+ X With PersonBlk.Person Do Begin X TimeTicked := DiffInTick(GetRealTime, LastHeal); X Amount := Attributes`5BATT_CON`5D*TimeTicked Div 10000; X If (Amount > 0) And (PersonBlk.Person.Health > 0) Then Begin X If (Health < MaxHealth) Then Begin X If (Amount + Health) > Maxhealth Then X Health := MaxHealth X Else Health := Amount + Health; X LogHealth := True; X End; X If (Mana < MaxMana) Then Begin X If (Amount + Mana) > Maxmana Then X Mana := Maxmana X Else Mana := Mana + Amount; X LogMana := True; X End; X LastHeal := GetRealTime; X Update_Record(FILE_BLOCK, Entity.PersonId, IAddress(PersonBlk)); X If LogHealth Then Begin X LogEvent(EntityId, 0, EV_HEALTH, Where, '', FALSE, X HealthLevel(Health, Maxhealth)); X If (EntityId = MyEntityId) Then X DescHealth('You', HealthLevel(Health, maxhealth), TRUE); X End; X End Else Begin X Free_Record(FILE_BLOCK); X If (Health = 0) Then X Resurrect(Entity, PersonBlk, EntityId, Where, (EntityId = MyEntityId V)); X End; X End; (* with *) XEnd; X X`5BGlobal`5D XProcedure Driver; XVar FirstCall : `5BStatic`5D Boolean := True; X TickerCheck : `5BStatic`5D Integer; X TickerHeal : `5BStatic`5D Integer; X TickerNpc : `5BStatic`5D Integer; XBegin X If InPlay Then Begin X If FirstCall Then Begin X FirstCall := False; X TickerCheck := GetTick; X TickerHeal := GetTick; X TickerNpc := GetTick; X End; X If TickerCheck < GetTick Then Begin X TickerCheck := TickerCheck + 2; X CheckEvent; X End; X If TickerHeal < GetTick Then Begin (* healing and more.. *) X TickerHeal := TickerHeal + 3000; X TimeHeal(MyEntityId, MyLocation); X End; X If TickerNpc < GetTick Then Begin X TickerNpc := TickerNpc + 3; X If (Not ImDead) Then X DriveEnemyList; X End; X End; XEnd; X X`5BHidden`5D XProcedure GainExp(EntityId : $UWord; ExpGained : Integer; X Print, IsKill : Boolean); XVar Index, OldLevel : Integer; X S : String_Type; X Entity : EntityType; X PersonBlk : BlockType; XBegin X Read_Record(FILE_ENTITY, EntityId, IAddress(Entity)); X Get_Record(FILE_BLOCK, Entity.PersonId, IAddress(PersonBlk)); X With PersonBlk.Person Do Begin X OldLevel := Level; X Repeat X If (Exp + ExpGained) >= LevelExpTable`5BLevel+1`5D Then Begin X Level := Level + 1; X Exp := LevelExpTable`5BLevel`5D; X Index := Rnd(MaxPersonAttri-1)+1; X Attributes`5BIndex`5D := Attributes`5BIndex`5D + Rnd(2); X ExpGained := (ExpGained + Exp - LevelExpTable`5BLevel`5D) Mod 2; X End Else Begin X Exp := Exp + ExpGained; X ExpGained := 0; X End; X Until (ExpGained = 0); X End; X Update_Record(FILE_BLOCK, Entity.PersonId, IAddress(PersonBlk)); X If Print And (PersonBlk.Person.Level > OldLevel) Then Begin X WriteV(S, 'You have gained ', (PersonBlk.Person.Level-OldLevel):0, ' lev Vel! '); X PutLine(S); X End; XEnd; X XProcedure Freeze(T : Real; Id : $UWord); XVar EndTime : Integer; X Entity : EntityType; X PersonBlk : BlockType; XBegin X If (Id = MyEntityId) Then Begin X EndTime := GetTick + Round(T * 10); X While (GetTick < EndTime) Do Begin X Wait(0.1); X Driver; X End; X End Else Begin X ReadEntity(Id, Entity); X Get_Record(FILE_BLOCK, Entity.PersonId, IAddress(PersonBlk)); X PersonBlk.Person.ActionDelay := PersonBlk.Person.ActionDelay+Round(T*10) V; X Update_Record(FILE_BLOCK, Entity.PersonId, IAddress(PersonBlk)); X End; XEnd; X XProcedure HandleEvent; (* forward *) XVar Entity, TargEntity : EntityType; X AnExit : ExitType; X Print : Boolean; X X Procedure HandleMoveIn; (* P1 : exit id; P2 : room index *) X Begin X With AnEvent Do Begin X ReadExit(Parms`5B1`5D, AnExit); X If Not PrintDesc(AnExit.InDesc`5BParms`5B2`5D`5D, Entity.Name) Then X PutLine(Entity.Name+' came into the room from '+ X DirTable`5BAnExit.Dire`5BParms`5B2`5D`5D`5D+'.'); X If Print Then UpdateRoomNpc(FALSE, Sender); X End; X End; X X Procedure HandleMoveOut; (* P1 : exit id; P2 : room index *) X Begin X With AnEvent Do Begin X ReadExit(Parms`5B1`5D, AnExit); X If Not PrintDesc(AnExit.OutDesc`5BParms`5B2`5D`5D, Entity.Name) Then X PutLine(Entity.Name+' has gone '+ X DirTable`5BAnExit.Dire`5BParms`5B2`5D`5D`5D+'.'); X If Print Then UpdateRoomNpc(TRUE, Sender); X End; X End; X X Procedure HandleMoveFail; (* P1 : exit id; P2 : room index *) X Begin X With AnEvent Do Begin X ReadExit(Parms`5B1`5D, AnExit); X If Not PrintDesc(AnExit.FailDesc`5BParms`5B2`5D`5D, Entity.Name) Then X PutLine(Entity.Name+' fails to go '+ X DirTable`5BAnExit.Dire`5BParms`5B2`5D`5D`5D+'.'); X End; X End; X X Procedure HandleAttack; (* P1 : damage; P2 : weapon id *) `20 X Var WeaponEntity : EntityType; X PersonBlk : BlockType; X AttkEffect : EffPtr_Type; X ExpGained : Integer := 0; X WasDead : Boolean := False; X Begin X With AnEvent Do Begin X If (Target = EntityId) Then Begin X If Print Then DescAttack(Entity.Name, 'you'); X If (Parms`5B2`5D > 0) Then Begin X ReadEntity(Parms`5B2`5D, WeaponEntity); X AttkEffect := WeaponEntity.AttEffect; X End Else AttkEffect := Zero; X AffectPerson(AttkEffect, Target, Location, TargEntity, PersonBlk, X Parms`5B1`5D, ExpGained, WasDead, Print, FALSE); X If Not WasDead And (PersonBlk.Person.Health = 0) Then Begin X If Print Then ImDead := True; X LogEvent(EntityId, Sender, EV_KILLED, Location, '',`20 X (Entity.Driver = 0), ExpGained); X End Else Begin X LogEvent(EntityId, 0, EV_HEALTH, Location, '', FALSE, X HealthLevel(PersonBlk.Person.Health, PersonBlk.Person.Maxhealth)); X End; X End Else If Print Then X DescAttack(Entity.Name, TargEntity.Name); X End; X End; X X Procedure HandleHealth; (* P1: health level *) X Begin X With AnEvent Do Begin X If (Sender = EntityId) Then X DescHealth('You', Parms`5B1`5D, TRUE) X Else DescHealth(Entity.Name, Parms`5B1`5D, FALSE); X End; X End; X X Procedure HandleKilled; (* P1: experience *) X Begin X With AnEvent Do Begin X If (Target = EntityId) Then Begin X If Print Then PutLine('You have killed '+Entity.Name+'! '); X GainExp(EntityId, Parms`5B1`5D, Print, TRUE); X End Else If Print Then X PutLine(Entity.Name+' has been slain by '+TargEntity.Name+'! '); X End; X End; X X Procedure HandleSay; X Begin X With AnEvent Do Begin X PutLine(Entity.Name+' says, " '+Msg+' "'); X End; X End; X X Procedure HandleCast; (* P1: spell id; P2 : direction; *) X Var (* P3: location *) X Damage, ExpGained : Integer := 0; X WasDead : Boolean := False; X PersonBlk : BlockType; X Spell : EntityType; X Begin X With AnEvent Do Begin X ReadEntity(Parms`5B1`5D, Spell); X If (Target = EntityId) Or (Target = ALL_TARGET) Then Begin X If (Target = ALL_TARGET) Then X ReadEntity(EntityId, TargEntity); X If Print Then Begin X DescSpellAttack(Entity.Name, 'you', Spell.Name, (Parms`5B3`5D <> Lo Vcation), X (Target = ALL_TARGET)); X End; X AffectPerson(Spell.SpellEffect, EntityId, Location, TargEntity,`20 X PersonBlk, Damage, ExpGained, WasDead, Print, FALSE); X If Not WasDead And (PersonBlk.Person.Health = 0) Then Begin X LogEvent(EntityId, Sender, EV_KILLED, Location, '',`20 X (Entity.Driver = 0), ExpGained); X If (Location <> Parms`5B3`5D) Then X LogEvent(EntityId, Sender, EV_KILLED, Parms`5B3`5D, '',`20 X (Entity.Driver = 0), ExpGained); X End Else Begin X LogEvent(EntityId, 0, EV_HEALTH, Location, '', FALSE, X HealthLevel(PersonBlk.Person.Health, PersonBlk.Person.Maxhealth)); X End; X End Else If Print Then X DescSpellAttack(Entity.Name, TargEntity.Name, Spell.Name, X (Parms`5B3`5D <> Location), FALSE); X End; X End; X X Procedure HandleFreeze; (* P1: delay time *) X Begin X With AnEvent Do Begin X If (Target = EntityId) Then Begin X If Print Then PutLine('You can''t move! '); X Freeze(Parms`5B1`5D, EntityId); X End Else If Print Then X PutLine(TargEntity.Name+' is frozen. '); X End; X End; X X Procedure HandleTeleport; (* P1: destination *) X Var NodeIn : EntityType; X OldPos : $UWord := 0; X Begin X With AnEvent Do Begin X If (Target = EntityId) Then Begin X ReadEntity(Location, NodeIn); X TakeToken(Target, NodeIn.RoomMapId, OldPos); X ReadEntity(Parms`5B1`5D, NodeIn); X PutToken(Target, Parms`5B1`5D, NodeIn.RoomMapId, OldPos, TRUE); X LogEvent(Target, 0, EV_INFORM, Parms`5B1`5D, TargEntity.Name+ X ' appears in a puff of purple smoke. ', FALSE); X If Print Then Begin X MyLocation := Parms`5B1`5D; X SetMyEvent; X DescRoomIn(NodeIn, EntityId, TRUE, IsWindy, IsWindy); X End; X End Else If Print Then X PutLine(TargEntity.Name+' vanished in a puff of purple smoke. '); X End; X End; X XBegin X Print := (EntityId = MyEntityId); X With AnEvent Do X If ((Location = Loc) Or (Location = GLOB_LOCATION)) And X ((Sender <> EntityId) Or IsWindy Or (Action = EV_HEALTH)) Then Begin X If (Sender > 0) Then X ReadEntity(Sender, Entity); (* gonna need this *) X If (Target > 0) And (Target < ALL_TARGET) Then X ReadEntity(Target, TargEntity); X Case Action Of X EV_INFORM : If Print Then PutLine(Msg); X EV_MOVE_IN : If Print Then HandleMoveIn; X EV_MOVE_OUT : If Print Then HandleMoveOut; X EV_MOVE_FAIL : If Print Then HandleMoveFail; X EV_ATTACK : HandleAttack; X EV_HEALTH : If Print Then HandleHealth; X EV_KILLED : HandleKilled; X EV_SAY : If Print Then HandleSay; X EV_CAST : HandleCast; X EV_FREEZE : HandleFreeze; X EV_TELEPORT : HandleTeleport; X End; X End; XEnd; X XEnd. $ CALL UNPACK M7_3.PAS;1 1730838256 $ create 'f' X X`5BInherit('M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M7_2','M7_3'), X Environment('M9')`5D X XModule M9; X X X`5BExternal, Hidden`5D XProcedure UpdateEnemyList(Id : $UWord; Var Npc : EntityType); External; X X(* action functions *) X XFunction CanAct(Var PersonBlk : BlockType): Boolean; XBegin X With PersonBlk.Person Do Begin X CanAct := (DiffInTick(GetRealTime, LastAct) > ActionDelay); X End; XEnd; X XFunction MovePerson(Var Entity, NodeIn : EntityType;`20 X Var PersonBlk, RoomBlk : BlockType; Var Location : $UWord; X EntityId, Dir : $UWord; Print : Boolean; X MoveHidden, MoveInvisi : Boolean := False): Boolean; XVar NodeTo : EntityType; AnExit : ExitType; X OldPos, NewPos, Origin, Dest : $UWord;`20 X Moved : Boolean := False; X Dummy1, Dummy2 : Integer := 0; X Dummy3 : Boolean := False; X X Function CanPass: Boolean; X Var GuardPos, Guardian : $UWord; X Begin X Case Dir Of X NORTH : GuardPos := POS_GUARD_N; X SOUTH : GuardPos := POS_GUARD_S; X WEST : GuardPos := POS_GUARD_W; X EAST : GuardPos := POS_GUARD_E; X UP : GuardPos := POS_GUARD_U; X DOWN : GuardPos := POS_GUARD_D; X End; X If LookUpMap(Guardian, NodeIn.RoomMapId, 0, FALSE, TRUE, GuardPos) Then X CanPass := (EntityId = Guardian) X Else CanPass := True; X End; X X Procedure SetIndex; X Begin X ReadExit(RoomBlk.Room.Exits`5BDir`5D, AnExit); X If (AnExit.Node`5B1`5D = Location) Then Begin X Origin := 1; X Dest := 2; X End Else Begin X Origin := 2; X Dest := 1; X End; X End; X XBegin X If (RoomBlk.Room.Exits`5BDir`5D > 0) Then Begin X If CanPass Then Begin X SetIndex; X If Not HaveEffect(AnExit.Effect, Entity, PersonBlk, Print, FALSE) Then V Begin X If TakeToken(EntityId, NodeIn.RoomMapId, OldPos) Then Begin X If (OldPos = POS_HIDDEN) And (MoveHidden) Then Begin X NewPos := POS_HIDDEN; X If Print Then PutLine('You move under the shadow. '); X End Else If (OldPos = POS_INVISI) And (MoveInvisi) Then Begin X NewPos := POS_INVISI; X If Print Then PutLine('You move invisiblely. '); X End Else Begin X NewPos := POS_IN_ROOM; X LogEvent(EntityId, 0, EV_MOVE_OUT, Location, '', FALSE, X RoomBlk.Room.Exits`5BDir`5D, Origin); X End; X Freeze(200.0/PersonBlk.Person.MaxSpeed, EntityId); X AffectPerson(AnExit.Effect, EntityId, Location, Entity, PersonBlk, X Dummy1, Dummy2, Dummy3, Print, FALSE); X ReadEntity(AnExit.Node`5BDest`5D, NodeTo); X If PutToken(EntityId, AnExit.Node`5BDest`5D, NodeTo.RoomMapId, New VPos, X TRUE) Then Begin X Location := AnExit.Node`5BDest`5D; (* return value *) X LogEvent(EntityId, 0, EV_MOVE_IN, Location, '', FALSE, X RoomBlk.Room.Exits`5BDir`5D, Dest); X Moved := True; X End Else LogErr('Fatal Error: MovePerson: PutToken '); X End Else LogErr('Fatal Error: MovePerson: TakeToken '); X End Else LogEvent(EntityId, 0, EV_MOVE_FAIL, Location, '', FALSE, X RoomBlk.Room.Exits`5BDir`5D, Origin); X End Else If Print Then PutLine('Your way is blocked! '); X End Else If Print Then PutLine('You can''t go that way! '); X MovePerson := Moved; XEnd; X XProcedure GetObj(Var Entity, NodeIn : EntityType; X Var PersonBlk : BlockType; X EntityId, Where, What : $UWord; X Print : Boolean := False); XVar Obj : EntityType; X OldPos : $UWord := 0; X Dummy1, Dummy2 : Integer := 0; X Dummy3 : Boolean := False; XBegin X ReadEntity(What, Obj); X If Not HaveEffect(Obj.GetEffect, Entity, PersonBlk, Print, FALSE) Then Beg Vin X If TakeToken(What, NodeIn.RoomMapId, OldPos) Then Begin X If PutToken(What, EntityId, Entity.InvenId, POS_INVEN, FALSE) Then Beg Vin X If Print Then PutLine('You have taken a(n) '+Obj.Name+'.'); X LogEvent(EntityId, 0, EV_INFORM, Where, Entity.Name+' took a(n) ' +-+-+-+-+-+-+-+- END OF PART 11 +-+-+-+-+-+-+-+-