{
Summary:
Character update & regeneration routines
## $Id: update.pas,v 1.8 2004/03/26 21:14:27 hemko Exp $
}
unit update;
interface
uses
chars,
dtypes,
area,
constants,
util,
timers,
skills;
procedure regenerate_chars();
procedure update_chars();
procedure update_tracks();
procedure update_teleports();
procedure update_time();
procedure gain_condition(ch : GCharacter; iCond, value : integer);
procedure battlegroundMessage();
procedure startBattleground();
procedure update_battleground();
procedure update_objects();
implementation
uses
SysUtils,
mudsystem,
commands,
fight,
conns,
player,
Channels;
// Regenerate characters
procedure regenerate_chars();
var
hp_gain, mv_gain, mana_gain : integer;
ch : GCharacter;
iterator : GIterator;
begin
iterator := char_list.iterator();
while (iterator.hasNext()) do
begin
ch := GCharacter(iterator.next());
hp_gain:=0; mv_gain:=0; mana_gain:=0;
if (not ch.IS_NPC) then
with ch do
begin
case state of
STATE_SLEEPING: begin
hp_gain:=9;
mv_gain:=7;
mana_gain:=3;
end;
STATE_RESTING: begin
hp_gain:=7;
mv_gain:=9;
mana_gain:=4;
end;
STATE_MEDITATING: begin
hp_gain:=6;
mv_gain:=6;
mana_gain:=10;
end;
STATE_IDLE: begin
hp_gain:=2;
mv_gain:=2;
mana_gain:=1;
end;
STATE_FIGHTING: begin
hp_gain:=0;
mv_gain:=1;
mana_gain:=0;
end;
end;
if IS_SET(ch.aff_flags,AFF_POISON) then
begin
hp_gain := hp_gain div 4;
mv_gain := mv_gain div 3;
mana_gain := mana_gain div 2;
end;
if (ch.room.flags.isBitSet(ROOM_MANAROOM)) then
mana_gain := mana_gain*2;
hp := UMin(hp + hp_gain, max_hp);
mv := UMin(mv + mv_gain, max_mv);
mana := UMin(mana + mana_gain, max_mana);
end
else
begin
// update progress of running gmc scripts
GNPC(ch).context.run();
end;
end;
iterator.Free();
end;
// Update the time
procedure update_time();
var
buf : string;
iterator : GIterator;
ch : GCharacter;
begin
inc(time_info.hour);
buf := '';
case time_info.hour of
1:begin
time_info.sunlight := SUN_DARK;
buf := 'The moon sets.';
end;
5:begin
time_info.sunlight:=SUN_DAWN;
buf := 'The day has begun.';
end;
6:begin
time_info.sunlight:=SUN_RISE;
buf := 'The sun rises in the east.';
end;
12:begin
time_info.sunlight:=SUN_LIGHT;
buf := 'It''s noon.';
end;
19:begin
time_info.sunlight:=SUN_SET;
buf := 'The sun slowly disappears in the west.';
end;
20:begin
time_info.sunlight:=SUN_MOON;
buf := 'The night has begun, the moon slowly rises.';
end;
24:begin
time_info.hour:=0;
inc(time_info.day);
end;
end;
if (time_info.day>=30) then
begin
time_info.day:=1;
inc(time_info.month);
end;
if (time_info.month>=17) then
begin
time_info.month:=1;
{ it wouldn't be Grendel without this :) - Grimlord }
to_channel(nil, 'The sky lights up with colorful flashes, created by the firework masters.'#13#10, CHANNEL_ALL, AT_GREY);
inc(time_info.year);
end;
if (length(buf) > 0) then
begin
iterator := char_list.iterator();
while (iterator.hasNext()) do
begin
ch := GCharacter(iterator.next());
if (ch.IS_NPC) then
continue;
if (ch.IS_OUTSIDE) and (ch.IS_AWAKE) then
act(AT_REPORT,buf,false,ch,nil,nil,TO_CHAR);
end;
iterator.Free();
end;
end;
// Improve mental state
procedure better_mental_state(ch : GCharacter; modifier : integer);
var
c : integer;
begin
c := URANGE(0, abs(modifier), 20);
if (number_percent < ch.con) then
inc(c);
if (ch.mental_state < 0) then
ch.mental_state := URANGE(-MAX_COND, ch.mental_state + c, 0)
else
if (ch.mental_state > 0) then
ch.mental_state := URANGE(0, ch.mental_state-c, MAX_COND);
end;
// Worsen mental state
procedure worsen_mental_state(ch : GCharacter; modifier : integer);
var
c : integer;
begin
c := URANGE(0, abs(modifier), 20);
if (number_percent < ch.con) then
dec(c);
if (c<1) then exit;
if (ch.mental_state < 0) then
ch.mental_state := URANGE(-MAX_COND, ch.mental_state-c, MAX_COND)
else
if (ch.mental_state > 0) then
ch.mental_state := URANGE(-MAX_COND, ch.mental_state+c, MAX_COND)
else
dec(ch.mental_state,c);
end;
procedure gain_condition(ch : GCharacter; iCond, value : integer);
var
condition, retcode : integer;
begin
if (value = 0) or (ch.IS_NPC) or (ch.IS_IMMORT) then
exit;
condition := GPlayer(ch).condition[iCond];
GPlayer(ch).condition[iCond]:=URANGE(0, condition+value, MAX_COND);
retcode := RESULT_NONE;
if (GPlayer(ch).condition[iCond]=0) then
case iCond of
COND_FULL:begin
act(AT_REPORT,'You are STARVING!',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n is starving and looks awfully weak!',false,ch,nil,nil,TO_ROOM);
worsen_mental_state(ch,1);
retcode:=damage(ch,ch,1,TYPE_SILENT);
end;
COND_THIRST:begin
act(AT_REPORT,'You are DYING of THIRST!',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n is dying of thirst!',false,ch,nil,nil,TO_ROOM);
worsen_mental_state(ch,2);
retcode:=damage(ch,ch,2,TYPE_SILENT);
end;
COND_DRUNK:begin
if condition<>0 then
act(AT_REPORT,'You are sober again.',false,ch,nil,nil,TO_CHAR);
retcode:=RESULT_NONE;
end;
COND_HIGH:begin
if condition<>0 then
act(AT_REPORT,'Your mind stops floating and resumes its normal course.',false,ch,nil,nil,TO_CHAR);
retcode:=RESULT_NONE;
end;
COND_CAFFEINE:begin
if condition<>0 then
act(AT_REPORT,'Your vains are clear of caffeine... you are less tense.',false,ch,nil,nil,TO_CHAR);
retcode:=RESULT_NONE;
end;
else begin
bugreport('gain_condition', 'update.pas', 'invalid condition: '+inttostr(icond));
retcode:=RESULT_NONE;
end;
end;
if (retcode<>RESULT_NONE) then { don't want to continue when ch is dead }
exit;
if (GPlayer(ch).condition[iCond]=3) then
case iCond of
COND_FULL:begin
act(AT_REPORT,'You are getting really hungry.',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'You can hear $n''s stomach growling, $e must be hungry.',false,ch,nil,nil,TO_ROOM);
if random(2)=0 then
worsen_mental_state(ch,1);
end;
COND_THIRST:begin
act(AT_REPORT,'You are getting really thirsty.',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n gasps and looks thirsty.',false,ch,nil,nil,TO_ROOM);
worsen_mental_state(ch,1);
end;
COND_DRUNK:if condition<>0 then
act(AT_REPORT,'The world is coming back into perspective.',false,ch,nil,nil,TO_CHAR);
COND_HIGH:if condition<>0 then
act(AT_REPORT,'You are slowly returning from outer space...',false,ch,nil,nil,TO_CHAR);
end;
if (GPlayer(ch).condition[iCond]=8) then
case iCond of
COND_FULL:act(AT_REPORT,'You are hungry.',false,ch,nil,nil,TO_CHAR);
COND_THIRST:act(AT_REPORT,'You are thirsty.',false,ch,nil,nil,TO_CHAR);
COND_DRUNK:if condition<>0 then
act(AT_REPORT,'You feel a bit less light headed.',false,ch,nil,nil,TO_CHAR);
COND_HIGH:if condition<>0 then
act(AT_REPORT,'Slowly but surely, your high is starting to wear off.',false,ch,nil,nil,TO_CHAR);
end;
if (GPlayer(ch).condition[iCond]=16) then
case iCond of
COND_FULL:act(AT_REPORT,'You could use a bite of something.',false,ch,nil,nil,TO_CHAR);
COND_THIRST:act(AT_REPORT,'A drink would be nice.',false,ch,nil,nil,TO_CHAR);
COND_DRUNK:act(AT_REPORT,'You feel as if little pixies feast inside your skull.',false,ch,nil,nil,TO_CHAR);
end;
end;
// Update characters
procedure update_chars();
var
p : integer;
ch : GCharacter;
e : GExit;
r : GRoom;
iterator : GIterator;
begin
iterator := char_list.iterator();
while (iterator.hasNext()) do
begin
ch := GCharacter(iterator.next());
if (ch.IS_NPC) then
begin
{ switched mobs don't wander }
if (ch.snooped_by <> nil) and (GPlayer(ch.snooped_by).switching = ch) then
continue;
if (not IS_SET(GNPC(ch).act_flags, ACT_SENTINEL)) and (ch.state = STATE_IDLE) then
begin
p := random(6)+1;
e := ch.room.findExit(p);
if (e <> nil) then
begin
r := findRoom(e.vnum);
if (r <> nil) and not (IS_SET(GNPC(ch).act_flags, ACT_STAY_AREA) and (r.area <> ch.room.area)) then
interpret(ch, headings[p]);
end;
end;
GNPC(ch).context.runSymbol('onTick', [integer(ch)]);
end
else
if (not ch.IS_NPC) then
begin
if (GPlayer(ch).condition[COND_DRUNK] > 8) then
worsen_mental_state(ch,GPlayer(ch).condition[COND_DRUNK] div 8);
if (GPlayer(ch).condition[COND_FULL] > 1) then
case ch.position of
STATE_SLEEPING: better_mental_state(ch, 4);
STATE_RESTING: better_mental_state(ch, 3);
STATE_IDLE: better_mental_state(ch, 2);
STATE_FIGHTING: if (random(4) = 0) then
better_mental_state(ch, 1);
end;
if (GPlayer(ch).condition[COND_THIRST] > 1) then
case ch.position of
STATE_SLEEPING: better_mental_state(ch, 5);
STATE_RESTING: better_mental_state(ch, 3);
STATE_IDLE: better_mental_state(ch, 2);
STATE_FIGHTING: if (random(4) = 0) then
better_mental_state(ch, 1);
end;
gain_condition(ch,COND_DRUNK, -1);
gain_condition(ch,COND_HIGH, -1);
gain_condition(ch,COND_FULL, -1);
case ch.room.sector of
SECT_DESERT:gain_condition(ch,COND_THIRST,-2);
SECT_UNDERWATER,
SECT_OCEANFLOOR:if random(2)=0 then
gain_condition(ch,COND_THIRST,-1);
else gain_condition(ch,COND_THIRST,-1);
end;
if (ch.mental_state>=30) then
case (ch.mental_state+5) div 10 of
3:begin
act(AT_REPORT,'You feel chilly and not well.',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n doesn''t look $s normal self.',false,ch,nil,nil,TO_ROOM);
end;
4:begin
act(AT_REPORT,'You don''t feel good at all.',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n doesn''t look too good.',false,ch,nil,nil,TO_ROOM);
end;
5:begin
act(AT_REPORT,'You need help immediately!',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n looks like $e could use your help.',false,ch,nil,nil,TO_ROOM);
end;
6:begin
act(AT_REPORT,'You are in BAD shape, get a healer!',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n looks awful and could use assistance.',false,ch,nil,nil,TO_ROOM);
end;
7:begin
act(AT_REPORT,'You lose your grip on reality... what is happening?',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n seems unaware of the world and $s surroundings.',false,ch,nil,nil,TO_ROOM);
end;
8:begin
act(AT_REPORT,'Understanding and knowledge flow through your mind.',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n runs about, babbling like an escaped madman!',false,ch,nil,nil,TO_ROOM);
end;
9:begin
act(AT_REPORT,'You feel like... Thor.',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n stands ranting about $s immortality.',false,ch,nil,nil,TO_ROOM);
end;
10:begin
act(AT_REPORT,'Your brain is a cloud of fog... you are dying.',false,ch,nil,nil,TO_CHAR);
act(AT_REPORT,'$n kneels down, muttering and chanting in tongues...',false,ch,nil,nil,TO_ROOM);
end;
end;
end;
end;
iterator.Free();
end;
procedure teleportChar(ch : GCharacter;room:GRoom);
begin
if (room.flags.isBitSet(ROOM_PRIVATE)) then
exit;
act(AT_REPORT,'$n disappears suddenly!',false,ch,nil,nil,TO_ROOM);
act(AT_REPORT,'You feel dizzy as you are transferred to another place...',false,ch,nil,nil,TO_CHAR);
ch.fromRoom;
ch.toRoom(room);
act(AT_REPORT,'$n appears in a puff of smoke.',false,ch,nil,nil,TO_ROOM);
interpret(ch,'look _AUTO');
end;
// Update tracks
procedure update_tracks();
var
iterator_room : GIterator;
node_track, node_tracknext : GListNode;
room : GRoom;
track : GTrack;
begin
iterator_room := room_list.iterator();
while (iterator_room.hasNext()) do
begin
room := GRoom(iterator_room.next());
node_track := room.tracks.head;
while (node_track <> nil) do
begin
node_tracknext := node_track.next;
track := GTrack(node_track.element);
dec(track.life);
if (track.life = 0) then
begin
room.tracks.remove(node_track);
track.Free();
end;
node_track := node_tracknext;
end;
end;
iterator_room.Free();
end;
// Update teleports
procedure update_teleports();
var
tele : GTeleport;
room, dest : GRoom;
iterator : GIterator;
begin
iterator := teleport_list.iterator();
while (iterator.hasNext()) do
begin
tele := GTeleport(iterator.next());
dec(tele.timer);
if (tele.timer = 0) then
begin
room := tele.t_room;
dest := findRoom(room.televnum);
while (room.chars.size() > 0) do
teleportChar(GCharacter(room.chars.head.element), dest);
teleport_list.remove(tele.node);
end;
end;
iterator.Free();
end;
{ procedure update_timers;
var
timer : GTimer;
node, node_next : GListNode;
begin
node := timer_list.head;
while (node <> nil) do
begin
timer := node.element;
node_next := node.next;
dec(timer.rounds);
if (timer.rounds = 0) then
begin
timers.remove(node);
if assigned(timer.spec_func) then
timer.spec_func(timer.ch,timer.victim,timer.sn);
timer.Free;
end;
node := node_next;
end;
end; }
procedure battlegroundMessage();
begin
if (bg_info.prize<>nil) then
to_channel(nil,pchar('[$B$7Battleground starting in '+inttostr(bg_info.count)+' seconds$A$7]'#13#10+
'Allowed levels: '+inttostr(bg_info.lo_range)+
'-'+inttostr(bg_info.hi_range)+' Prize: '+ GObject(bg_info.prize).short),CHANNEL_ALL,AT_REPORT)
else
to_channel(nil,pchar('[$B$7Battleground starting in '+inttostr(bg_info.count)+' seconds$A$7]'#13#10+
'Allowed levels: '+inttostr(bg_info.lo_range)+
'-'+inttostr(bg_info.hi_range)),CHANNEL_ALL,AT_REPORT)
end;
procedure startBattleground();
var
iterator : GIterator;
ch : GCharacter;
s,vnum:integer;
begin
to_channel(nil,pchar('[$B$7Battleground starting NOW!$A$7]'),CHANNEL_ALL,AT_REPORT);
iterator := char_list.iterator();
while (iterator.hasNext()) do
begin
ch := GCharacter(iterator.next());
if (ch.IS_NPC) then
continue;
if (GPlayer(ch).conn.isPlaying) and (GPlayer(ch).bg_status = BG_JOIN)
and (ch.level >= bg_info.lo_range) and (ch.level <= bg_info.hi_range) then
begin
act(AT_REPORT,'You are transfered into the arena.',false,ch,nil,nil,TO_CHAR);
act(AT_GREEN,'Niet mokken, lekker knokken!',false,ch,nil,nil,TO_CHAR);
s := random(system_info.arena_end - system_info.arena_start + 1) + system_info.arena_start;
vnum := URange(system_info.arena_start, s, system_info.arena_end);
GPlayer(ch).bg_room := ch.room;
ch.fromRoom();
ch.toRoom(findRoom(vnum));
GPlayer(ch).bg_status := BG_PARTICIPATE;
interpret(ch,'look');
end;
end;
iterator.Free();
end;
procedure update_battleground();
var
s : integer;
ch, last : GCharacter;
iterator : GIterator;
begin
{ battleground is running, check to see if we have a winner }
if (bg_info.count = 0) then
begin
last := nil;
s := 0;
iterator := char_list.iterator();
while (iterator.hasNext()) do
begin
ch := GCharacter(iterator.next());
if (ch.IS_NPC) then
continue;
if (GPlayer(ch).conn.isPlaying()) and (GPlayer(ch).bg_status = BG_PARTICIPATE) then
begin
inc(s);
last := ch;
end;
end;
if (s = 0) then
begin
to_channel(nil,'[$B$7Battleground stopped without a winner.$A$7]',CHANNEL_ALL,AT_REPORT);
bg_info.count := -1;
end
else
if (s = 1) then
begin
to_channel(nil,'[$B$3'+last.name+'$B$7 has won the battleground!$A$7]',CHANNEL_ALL,AT_REPORT);
act(AT_REPORT,'Congratulations! You have won the battleground!',false,last,nil,nil,TO_CHAR);
inc(GPlayer(last).bg_points,3);
last.fromRoom();
last.toRoom(GPlayer(last).bg_room);
if (bg_info.prize <> nil) then
begin
act(AT_REPORT,'You have won $p.', false, last, bg_info.prize, nil, TO_CHAR);
GObject(bg_info.prize).toChar(last);
end;
interpret(last, 'look');
GPlayer(last).bg_status := BG_NOJOIN;
last.hp := last.max_hp;
bg_info.winner := last;
bg_info.count := -1;
bg_info.prize := nil;
end;
end;
end;
// Update objects
procedure update_objects();
var
obj : GObject;
rch : GCharacter;
msg : string;
at_temp : integer;
iterator : GIterator;
begin
iterator := objectList.iterator();
while (iterator.hasNext()) do
begin
obj := GObject(iterator.next());
if (IS_SET(obj.flags, OBJ_NODECAY)) then
continue;
if (obj.timer <= 0) then
continue;
dec(obj.timer);
if (obj.timer > 0) then
continue;
case obj.item_type of
ITEM_CORPSE : begin
msg := '$p decays into dust and blows away.';
at_temp := AT_CORPSE;
end;
ITEM_BLOOD : begin
msg := '$p dries up.';
at_temp := AT_RED;
end;
ITEM_FOOD : begin
msg := '$p slowly rots away, leaving a foul stench.';
at_temp := AT_REPORT;
end;
else
begin
msg := '$p vanishes in the wink of an eye.';
at_temp := AT_REPORT;
end;
end;
if (obj.carried_by <> nil) then
act(at_temp, msg, false, obj.carried_by, obj, nil, TO_CHAR)
else
if (obj.room <> nil) then
begin
if (obj.room.chars.head <> nil) then
rch := GCharacter(obj.room.chars.head.element)
else
rch := nil;
if (rch <> nil) and (not IS_SET(obj.flags, OBJ_HIDDEN)) then
begin
act(at_temp, msg, false, rch, obj, nil, TO_ROOM);
act(at_temp, msg, false, rch, obj, nil, TO_CHAR);
end;
end;
obj.Free();
end;
end;
end.