// $Id: cmd_skill.inc,v 1.14 2001/07/12 16:37:03 druid Exp $ procedure do_bash(ch:GCharacter;param:string); var chance:integer; vict:GCharacter; begin if (ch.LEARNED(gsn_bash) = 0) then begin ch.sendBuffer('You don''t know how to bash!'#13#10); exit; end; if (length(param) = 0) and (ch.position <> POS_FIGHTING) then begin act(AT_REPORT,'Bash whom?',false,ch,nil,nil,TO_CHAR); exit; end; if (ch.position = POS_BASHED) then begin ch.sendBuffer('You are bashed and cannot move!'#13#10); exit; end; if (ch.bash_timer > -2) then begin act(AT_REPORT,'You are still too off-balance from that last bash.',false,ch,nil,nil,TO_CHAR); exit; end; if (ch.bashing > -2) then begin act(AT_REPORT,'You cannot bash this soon after a bash!',false,ch,nil,nil,TO_CHAR); exit; end; vict := ch.room.findChar(ch, param); if (vict = nil) then if (ch.position = POS_FIGHTING) and (ch.fighting <> nil) then vict := ch.fighting; if (vict = nil) then ch.sendBuffer('They aren''t here.'#13#10) else if not in_melee(ch,vict) then begin act(AT_REPORT,'You aren''t on the front lines of that battle!',false,ch,nil,nil,TO_CHAR); exit; end else if (vict = ch) then begin ch.sendBuffer('You try to bash yourself and fall to the ground!'#13#10); act(AT_REPORT,'$n looks silly as $e tries to bash $mself.',false,ch,nil,nil,TO_ROOM); end else if (vict.IS_NPC) and (IS_SET(GNPC(vict).act_flags, ACT_SPIRIT) or IS_SET(GNPC(vict).act_flags, ACT_NOBASH)) then ch.sendBuffer('You can''t bash that kind of creature!'#13#10) else with ch do begin if fighting=nil then begin if IS_SET(ch.room.flags,ROOM_SAFE) then begin ch.sendBuffer('A strange force prevents you from attacking.'#13#10); exit; end else begin fighting:=vict; if (not ch.IS_NPC) then GPlayer(ch).fightxp:=0; end; end; chance := ch.LEARNED(gsn_bash); if (vict.bash_timer>0) then act(AT_REPORT,'$N is already bashed to the ground!',false,ch,nil,vict,TO_CHAR) else if (vict.bash_timer>-2) then act(AT_REPORT,'$N is still alert from the last bash.',false,ch,nil,vict,TO_CHAR) else if (number_percent <= chance) then begin // improve_skill(ch,gsn_bash); vict.position:=POS_BASHED; position:=POS_FIGHTING; vict.bash_timer:=6; bashing:=6; if vict.fighting=nil then vict.fighting:=ch; act(AT_GREEN,'Your powerful bash sends $N sprawling to the ground!',false,ch,nil,vict,TO_CHAR); act(AT_GREEN,'$n sends $N sprawling to the ground with a powerful bash!',false,ch,nil,vict,TO_ROOM); end else begin ch.setWait(8); act(AT_REPORT,'You miss the bash and almost fall over!',false,ch,nil,nil,TO_CHAR); act(AT_REPORT,'$n misses a bash at $N and almost falls over!',false,ch,nil,vict,TO_ROOM); position:=POS_FIGHTING; vict.position:=POS_FIGHTING; if vict.fighting=nil then vict.fighting:=ch; end; end; end; procedure do_kick(ch:GCharacter;param:string); var dam,chance:integer; vict:GCharacter; begin if (ch.LEARNED(gsn_kick) = 0) then begin ch.sendBuffer('You don''t know how to kick!'#13#10); exit; end; if (length(param)=0) and (ch.position<>POS_FIGHTING) then begin act(AT_REPORT,'Kick whom?',false,ch,nil,nil,TO_CHAR); exit; end; if (ch.position = POS_BASHED) then begin ch.sendBuffer('You are bashed and cannot move!'#13#10); exit; end; if (ch.bash_timer > -2) then begin act(AT_REPORT,'You are still too off-balance from that last bash.',false,ch,nil,nil,TO_CHAR); exit; end; if (ch.bashing > -2) then begin act(AT_REPORT,'You cannot kick this soon after a bash!',false,ch,nil,nil,TO_CHAR); exit; end; vict := ch.room.findChar(ch, param); if (vict = nil) then if (ch.position=POS_FIGHTING) and (ch.fighting<>nil) then vict:=ch.fighting; if (vict = nil) then act(AT_REPORT,'They aren''t here.',false,ch,nil,nil,TO_CHAR) else if not in_melee(ch,vict) then begin act(AT_REPORT,'You cannot reach $N!',false,ch,nil,vict,TO_CHAR); exit; end else if (vict = ch) then ch.sendBuffer('Painfully, you force your knee to bend in a way it isn''t supposed to.'#13#10) else with ch do begin if mv<12 then begin ch.sendBuffer('You don''t have enough energy to kick.'#13#10); exit; end; if (vict.CHAR_DIED) then exit; if fighting=nil then begin if IS_SET(ch.room.flags,ROOM_SAFE) then begin ch.sendBuffer('A strange force prevents you from attacking.'#13#10); exit; end else begin fighting:=vict; if (not ch.IS_NPC) then GPlayer(ch).fightxp:=0; end; end; ch.setWait(8); chance := ch.LEARNED(gsn_kick); if (vict.IS_NPC) and (IS_SET(GNPC(vict).act_flags, ACT_SPIRIT)) then begin ch.sendBuffer('You swing your leg and kick high, but it goes right through your victim!'#13#10); if vict.fighting=nil then vict.fighting:=ch; position:=POS_FIGHTING; vict.position:=POS_FIGHTING; end else if number_percent<=chance then begin //improve_skill(ch,gsn_kick); dam:=urange(1,rolldice(4,18),level div 6)*3; inc(dam,ch.apb); dam:=(dam*ch.str) div 50; damage(ch,ch.fighting,dam, integer(gsn_kick)); end else damage(ch,ch.fighting,0, integer(gsn_kick)); end; end; procedure do_fly(ch:GCharacter;param:string); begin if (ch.IS_FLYING) then ch.stopFlying else ch.startFlying; end; procedure do_sneak(ch:GCharacter;param:string); begin if IS_SET(ch.aff_flags,AFF_SNEAK) then begin ch.sendBuffer('You no longer sneak.'#13#10); REMOVE_BIT(ch.aff_flags,AFF_SNEAK); end else begin ch.sendBuffer('You attempt to move silently.'#13#10); SET_BIT(ch.aff_flags,AFF_SNEAK); end; end; procedure do_spells(ch : GCharacter; param : string); var a, targ : integer; buf : string; node : GListNode; g : GLearned; arr : array[TARGET_OFF_ATTACK..TARGET_OBJECT] of record num : integer; str : string; end; begin for a := TARGET_OFF_ATTACK to TARGET_OBJECT do begin arr[a].num := 0; arr[a].str := ''; end; arr[TARGET_OFF_ATTACK].str := add_chars(88, '$A$3--- $B$7[Offensive spells]$A$3 -', '-') + '$A$7'#13#10; arr[TARGET_OFF_AREA].str := add_chars(88, '$A$3--- $B$7[Offensive area spells]$A$3 -', '-') + '$A$7'#13#10; arr[TARGET_DEF_SELF].str := add_chars(88, '$A$3--- $B$7[Self-only spells]$A$3 -', '-') + '$A$7'#13#10; arr[TARGET_DEF_SINGLE].str := add_chars(88, '$A$3--- $B$7[Defensive spells]$A$3 -', '-') + '$A$7'#13#10; arr[TARGET_DEF_AREA].str := add_chars(88, '$A$3--- $B$7[Defensive area spells]$A$3 -', '-') + '$A$7'#13#10; arr[TARGET_DEF_WORLD].str := add_chars(88, '$A$3--- $B$7[World spells]$A$3 -', '-') + '$A$7'#13#10; arr[TARGET_OBJECT].str := add_chars(88, '$A$3--- $B$7[Object spells]$A$3 -', '-') + '$A$7'#13#10; with ch do begin node := skills_learned.head; while (node <> nil) do begin g := node.element; if (GSkill(g.skill).skill_type = SKILL_SPELL) then for targ := TARGET_OFF_ATTACK to TARGET_OBJECT do begin if (GSkill(g.skill).target = targ) then with arr[targ] do begin inc(num); if (odd(num)) then str := str + Format('%25s %3dMa %3d%%', [GSkill(g.skill).name, GSkill(g.skill).min_mana, g.perc]) + ' ' else str := str + Format('%-25s %3dMa %3d%%', [GSkill(g.skill).name, GSkill(g.skill).min_mana, g.perc]) + #13#10; end; end; node := node.next; end; end; buf := act_string(add_chars(80, '$A$3---- Known spells -', '-') + #13#10 + #13#10, ch, nil, nil, nil); for a := TARGET_OFF_ATTACK to TARGET_OBJECT do begin if (arr[a].num <> 0) then begin if odd(arr[a].num) then buf := buf + act_string(arr[a].str + #13#10#13#10, ch, nil, nil, nil) else buf := buf + act_string(arr[a].str + #13#10, ch, nil, nil, nil); end; end; if (not ch.IS_NPC()) then buf := buf + act_string('$A$7 Spellslots available: $B$7' + inttostr(GPlayer(ch).max_spells - GPlayer(ch).getUsedSpellslots()) + '$A$7'#13#10#13#10, ch, nil, nil, nil); delete(buf, length(buf) - 2, 2); ch.sendPager(buf); end; procedure do_skills(ch : GCharacter; param : string); var a : integer; buf : string; g : GLearned; node : GListNode; begin buf := ''; with ch do begin ch.sendPager(act_string(add_chars(80, '$A$3---- Known skills -', '-') + '$A$7'#13#10#13#10, ch, nil, nil, nil)); a := 0; node := ch.skills_learned.head; while (node <> nil) do begin g := node.element; if (GSkill(g.skill).skill_type <> SKILL_SPELL) then begin inc(a); if (odd(a)) then buf := buf + Format('%25s %3d%%', [GSkill(g.skill).name, g.perc]) + ' ' else buf := buf + Format('%-25s %3d%%', [GSkill(g.skill).name, g.perc]) + #13#10; end; node := node.next; end; if (odd(a)) then buf := buf + #13#10; if (not ch.IS_NPC()) then buf := buf + act_string(#13#10'$A$7 Skillslots available: $B$7' + inttostr(GPlayer(ch).max_skills - GPlayer(ch).getUsedSkillslots()) + '$A$7'#13#10, ch, nil, nil, nil); ch.sendPager(act_string(buf, ch, nil, nil, nil)); end; end; procedure do_learn(ch:GCharacter;param:string); var sn : GSkill; node : GListNode; g : GLearned; vict,learn:GCharacter; begin vict := nil; learn := nil; if (ch.IS_NPC()) then begin ch.sendBuffer('This command doesn''t work for mobs.'#13#10); exit; end; node := ch.room.chars.head; while (node <> nil) do begin vict := node.element; if (vict.IS_NPC) and (vict.IS_LEARNER) then begin learn := vict; break; end; node := node.next; end; if (learn=nil) then begin ch.sendBuffer('You cannot learn anything here!'#13#10); exit; end else if (length(param)=0) then begin ch.sendBuffer('Skills you can learn here:'#13#10#13#10); node := vict.skills_learned.head; while (node <> nil) do begin g := node.element; // if (ch.LEARNED(g.skill) = 0) then if ((ch.level >= GSkill(g.skill).min_lvl) and (ch.LEARNED(g.skill) = 0)) then act(AT_REPORT, ' (Level $B$4' + pad_integer_front(GSkill(g.skill).min_lvl, 3) + '$A$7) ' + GSkill(g.skill).name^, false, ch, nil, nil, TO_CHAR); node := node.next; end; end else begin sn := findSkill(param); if (sn = nil) or (vict.LEARNED(sn) = 0) then act(AT_REPORT, '$N doesn''t teach this skill.',false,ch,nil,vict,TO_CHAR) else if ((sn.skill_type <> SKILL_SPELL) and (GPlayer(ch).max_skills - GPlayer(ch).getUsedSkillslots() <= 0)) then act(AT_REPORT, 'You have no more free skillslots!', false, ch, nil, nil, TO_CHAR) else if ((sn.skill_type = SKILL_SPELL) and (GPlayer(ch).max_spells - GPlayer(ch).getUsedSpellslots() <= 0)) then act(AT_REPORT, 'You have no more free spellslots!', false, ch, nil, nil, TO_CHAR) else { if (sn.skill_type = SKILL_SPELL) and (ch.skills_learned.getSize() = ch.race.max_spells) then act(AT_REPORT, 'You have reached the maximum number of spells for your race.', false, ch, nil, nil, TO_CHAR) else if (sn.skill_type = SKILL_SKILL) and (ch.skills_learned.getSize() = ch.race.max_skills) then act(AT_REPORT, 'You have reached the maximum number of spells for your race.', false, ch, nil, nil, TO_CHAR) else } begin if (ch.LEARNED(sn) = 0) then begin if (sn.min_lvl > ch.level) then ch.sendBuffer('You have not yet reached the appropiate level.'#13#10) else begin node := sn.prereqs.head; while (node <> nil) do begin if (ch.LEARNED(node.element) < 50) then begin ch.sendBuffer('You need to have sufficient knowledge of ' + GSkill(node.element).name^ + ' first.'#13#10); exit; end; node := node.next; end; act(AT_REPORT,'You learn ' + cap(sn.name^) + '.',false,ch,nil,nil,TO_CHAR); ch.SET_LEARNED(20, sn); end; end else act(AT_REPORT,'You have already learned that skill.',false,ch,nil,nil,TO_CHAR); end; end; end; procedure do_unlearn(ch:GCharacter;param:string); var sn : GSkill; begin if (length(param) = 0) then begin ch.sendBuffer('UNLEARN <skill or spell to unlearn>'#13#10#13#10); ch.sendBuffer('This is irreversible, and you won''t get any practice sessions back.'#13#10); exit; end; sn := findSkill(param); if (sn = nil) or (ch.LEARNED(sn) = 0) then act(AT_REPORT, 'You haven''t learned this skill.',false,ch,nil,nil,TO_CHAR) else begin ch.SET_LEARNED(0, sn); act(AT_REPORT, 'You have unlearned ' + sn.name^ + '.', false, ch, nil, nil, TO_CHAR); end; end; procedure do_practice(ch:GCharacter;param:string); var sn : GSkill; vict,learn:GCharacter; node : GListNode; g : GLearned; begin vict := nil; learn := nil; node := ch.room.chars.head; while (node <> nil) do begin vict := node.element; if (vict.IS_NPC) and (vict.IS_LEARNER) then begin learn := vict; break; end; node := node.next; end; if (learn=nil) then begin ch.sendBuffer('You cannot practice anything here!'#13#10); exit; end else if (length(param)=0) then begin ch.sendBuffer('Skills you can practice here:'#13#10#13#10); { for sn := 0 to MAX_SKILLS - 1 do begin if (vict.learsn] > 0) then act(AT_REPORT, ' (Level $B$4' + pad_integer_front(skill_table[sn].min_lvl, 3) + '$A$7) ' + skill_table[sn].name, false, ch, nil, nil, TO_CHAR); end; } node := vict.skills_learned.head; while (node <> nil) do begin g := node.element; if (ch.level >= GSkill(g.skill).min_lvl) then act(AT_REPORT, Format(' (Level $B$4%s$A$7) %-25s $B$7%s$A$7%%', [pad_integer_front(GSkill(g.skill).min_lvl, 3), GSkill(g.skill).name, pad_integer_front(ch.LEARNED(g.skill), 3)]), false, ch, nil, nil, TO_CHAR); node := node.next; end; end else begin sn := findSkillPlayer(ch,param); if (sn <> nil) then begin if (vict.LEARNED(sn) = 0) then act(AT_REPORT, '$N doesn''t teach this skill.', false, ch, nil, vict, TO_CHAR) else if (ch.LEARNED(sn) < 50) then begin if (GPlayer(ch).pracs < 1) then begin ch.sendBuffer('You don''t have enough practice sessions left!'#13#10); exit; end else dec(GPlayer(ch).pracs); // ch.SET_LEARNED(ch.LEARNED(sn) + 8, sn); // base skill gain on int ch.SET_LEARNED(ch.LEARNED(sn) + round(ch.int / 10) + random(4) - 2, sn); if (ch.LEARNED(sn) > 50) then begin ch.SET_LEARNED(50, sn); act(AT_REPORT,'You now know enough about ' + cap(sn.name^) + '.',false,ch,nil,nil,TO_CHAR); end else act(AT_REPORT,'You practice ' + cap(sn.name^) + '.',false,ch,nil,nil,TO_CHAR); end else act(AT_REPORT,'You have practiced this skill enough.',false,ch,nil,nil,TO_CHAR); end else act(AT_REPORT,'You have not learned this skill!',false,ch,nil,nil,TO_CHAR); end; end; procedure search_timer(ch, victim : GCharacter; sn : GSkill); var pexit : GExit; node : GListNode; begin ch.position := POS_STANDING; if skill_success(ch,sn) then begin { check for hidden exits first } node := ch.room.exits.head; while (node <> nil) do begin pexit := node.element; if (IS_SET(pexit.flags, EX_SECRET)) and (IS_SET(pexit.flags, EX_ISDOOR)) then begin if (length(pexit.keywords^) > 0) then act(AT_REPORT,'You uncover a $d!',false,ch,nil,pexit,TO_CHAR) else act(AT_REPORT,'You uncover a secret passage '+headings[pexit.direction]+'!',false,ch,nil,nil,TO_CHAR); REMOVE_BIT(pexit.flags, EX_SECRET); exit; end; node := node.next; end; ch.sendBuffer('You look around, but find nothing.'#13#10); end else ch.sendBuffer('You look around, but find nothing.'#13#10); end; procedure do_search(ch:GCharacter;param:string); begin ch.sendBuffer('You start searching...'#13#10); act(AT_REPORT,'$n looks around, searching for something...',false,ch,nil,nil,TO_ROOM); ch.position := POS_SEARCHING; registerTimer(TIMER_SEARCH, search_timer, 6, ch, nil, gsn_searching); end; procedure backstab_timer(ch,victim:GCharacter;sn:GSkill); var roll,to_hit:integer; dam:integer; wield : GObject; begin if (victim.CHAR_DIED) or (victim.room <> ch.room) or (not ch.CAN_SEE(victim)) then begin ch.sendBuffer('They are not here.'#13#10); ch.position:=POS_STANDING; exit; end; wield := ch.getWield(ITEM_WEAPON); to_hit:=ch.hitroll + 10; { +10 bonus because of backstab } inc(to_hit,victim.ac); inc(to_hit,(ch.LEARNED(sn) - 50) div 5); roll:=rolldice(1,100); if (roll<=to_hit) and (wield<>nil) then begin dam:=URange(1,rolldice(wield.value[2],wield.value[3])*(2+ch.level div 15),350); act(AT_REPORT,'Your weapon finds its point in $N''s back, causing $S body to spasm.',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'Before you know what happens, $n places $s weapon in your back!',false,ch,nil,victim,TO_VICT); act(AT_REPORT,'$n sneaks up behind $N''s back and places $s weapon into $S''s back.',false,ch,nil,victim,TO_NOTVICT); if (dam<=25) then begin act(AT_REPORT,'$N grimaces in pain as your blade pierces $S flesh.',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'You grimace in pain as $n''s blade pierces your flesh.',false,ch,nil,victim,TO_VICT); act(AT_REPORT,'$N grimaces in pain as $n''s blade pierces $S flesh.',false,ch,nil,victim,TO_NOTVICT); end else if (dam<=50) then begin act(AT_REPORT,'$N winces in agony as you stab $M in the back.',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'You wince in agony as $n stabs you in the back.',false,ch,nil,victim,TO_VICT); act(AT_REPORT,'$N winces in agony as $n stabs $M in the back.',false,ch,nil,victim,TO_NOTVICT); end else if (dam<=75) then begin act(AT_REPORT,'As you find a lung and pierce hard, $N cries out in pain!',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'You cry out in pain as $n pierces your lung!',false,ch,nil,victim,TO_VICT); act(AT_REPORT,'$N cries out in pain as $n pierces $S lung!',false,ch,nil,victim,TO_NOTVICT); end else if (dam<=100) then begin act(AT_REPORT,'$N spasms in terrible pain as you plunge your blade into $M.',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'You feel a terrible pain as $n plunges $s blade into you!',false,ch,nil,victim,TO_VICT); act(AT_REPORT,'$N spasms in terrible pain as $n plunges $s blade into $M.',false,ch,nil,victim,TO_NOTVICT); end else if (dam<=150) then begin act(AT_REPORT,'Blood runs over your hands as you forcefully stab $N!',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'You bleed hard as you are forcefully stabbed by $n!',false,ch,nil,victim,TO_VICT); act(AT_REPORT,'Blood runs over $n''s hands as $e forcefully stabs $N!',false,ch,nil,victim,TO_NOTVICT); end else if (dam<=200) then begin act(AT_REPORT,'As you pierce $N''s back, you twist your weapon multiple times!',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'$n pierces your back and twists $s blade multiple times!',false,ch,nil,victim,TO_VICT); act(AT_REPORT,'$n pierces $N''s back and twists $s blade multiple times!',false,ch,nil,victim,TO_NOTVICT); end else if (dam<=350) then begin act(AT_REPORT,'You find a mark in $N''s spine and thrust your blade through!',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'$n targets your spine and thrusts $s blade through!',false,ch,nil,victim,TO_VICT); act(AT_REPORT,'$n finds a mark in $N''s spine and thrusts $s blade through!',false,ch,nil,victim,TO_NOTVICT); end; damage(ch,victim,dam,cardinal(sn)); victim.fighting:=ch; end else begin act(AT_REPORT,'As you attempt to sneak behind $N''s back, you are uncovered!',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'$n failed to backstab $N!', false,ch,nil,victim,TO_ROOM); damage(ch,victim,0,cardinal(sn)); victim.fighting:=ch; end; end; procedure do_backstab(ch:GCharacter;param:string); var victim:GCharacter; wield:GObject; begin if (ch.LEARNED(gsn_backstab) = 0) then begin ch.sendBuffer('You don''t know how to backstab!'#13#10); exit; end; if (length(param)=0) then begin ch.sendBuffer('Backstab whom?'#13#10); exit; end; if (ch.position=POS_FIGHTING) then begin ch.sendBuffer('You cannot backstab while fighting!'#13#10); exit; end; victim := ch.room.findChar(ch, param); if (victim=nil) then begin ch.sendBuffer('They are not here.'#13#10); exit; end else if (victim=ch) then begin ch.sendBuffer('How would you sneak upon yourself?'#13#10); exit; end; wield := ch.getWield(ITEM_WEAPON); if (wield=nil) or not (wield.value[4] in [FG_PIERCE,FG_STAB]) then begin ch.sendBuffer('You must wield a piercing or stabbing weapon.'#13#10); exit; end; ch.sendBuffer('You move stealthily, attempting to get behind your target...'#13#10); registerTimer(TIMER_BACKSTAB, backstab_timer, 8, ch, victim, gsn_backstab); ch.position:=POS_BACKSTAB; end; procedure circle_timer(ch,victim:GCharacter; sn : GSkill); begin if (victim.CHAR_DIED) or (victim.room<>ch.room) then begin ch.sendBuffer('They are not here.'#13#10); ch.position:=POS_STANDING; exit; end; ch.position := POS_FIGHTING; if (number_percent <= ch.LEARNED(sn)) then begin act(AT_REPORT,'You succeed in circling your opponent and find yourself behind $M.',false,ch,nil,victim,TO_CHAR); backstab_timer(ch,victim,gsn_backstab); end else act(AT_REPORT,'You failed to circle.',false,ch,nil,nil,TO_CHAR); end; procedure do_circle(ch:GCharacter;param:string); var wield : GObject; begin if (ch.LEARNED(gsn_circle) = 0) then begin ch.sendBuffer('You don''t know how to circle!'#13#10); exit; end; if (ch.position <> POS_FIGHTING) then begin ch.sendBuffer('You are not fighting!'#13#10); exit; end; if (ch.fighting.fighting = ch) then begin ch.sendBuffer('You are on the frontline and can not circle!'#13#10); exit; end; wield := ch.getWield(ITEM_WEAPON); if (wield=nil) or not (wield.value[4] in [FG_PIERCE,FG_STAB]) then begin ch.sendBuffer('You must wield a piercing or stabbing weapon.'#13#10); exit; end; act(AT_REPORT,'You attempt to circle behind your target...',false,ch,nil,nil,TO_CHAR); registerTimer(TIMER_CIRCLE, circle_timer, 10, ch, ch.fighting, gsn_circle); ch.position:=POS_CIRCLE; end; procedure do_rescue(ch:GCharacter;param:string); var victim:GCharacter; begin if (ch.LEARNED(gsn_rescue) = 0) then begin ch.sendBuffer('You don''t know how to rescue!'#13#10); exit; end; if (length(param) = 0) then begin ch.sendBuffer('Rescue whom?'#13#10); exit; end; if (ch.position=POS_FIGHTING) and (ch.fighting.fighting=ch) then begin ch.sendBuffer('You are on the frontline and can not rescue!'#13#10); exit; end; victim := ch.room.findChar(ch, param); if (victim = nil) then begin ch.sendBuffer('That is not here!'#13#10); exit; end; if (number_percent <= ch.LEARNED(gsn_rescue)) then begin act(AT_REPORT,'You rescue $N!',false,ch,nil,victim,TO_CHAR); act(AT_REPORT,'$N rescues you!',false,victim,nil,ch,TO_VICT); act(AT_REPORT,'$N rescues $n!',false,victim,nil,ch,TO_NOTVICT); if (ch.position <> POS_FIGHTING) then begin ch.fighting := victim.fighting; ch.position := POS_FIGHTING; end; ch.fighting.fighting := ch; victim.fighting := nil; victim.position := POS_STANDING; end else begin act(AT_REPORT,'Your rescue attempt failed.',false,ch,nil,nil,TO_CHAR); ch.setWait(3); end; end; procedure track_timer(ch,victim:GCharacter; sn : GSkill); var node : GListNode; track : GTrack; begin if (not skill_success(ch, gsn_track)) then begin ch.sendBuffer('You can''t seem to find any tracks.'#13#10); exit; end; node := ch.room.tracks.head; track := nil; while (node <> nil) do begin if (GTrack(node.element).who = ch.tracking) and ((track = nil) or (track.life < GTrack(node.element).life)) then track := node.element; node := node.next; end; if (track = nil) then begin if (victim = nil) then begin ch.sendBuffer('The tracks seem to end here.'#13#10); ch.tracking := ''; end else ch.sendBuffer('You can''t seem to find any tracks.'#13#10) end else begin ch.sendBuffer('You see some tracks heading ' + headings[track.direction] + '!'#13#10); end; end; procedure do_track(ch : GCharacter; param : string); var vict : GCharacter; begin vict := nil; if (ch.LEARNED(gsn_track) = 0) then begin ch.sendBuffer('You don''t know how to track!'#13#10); exit; end; if (length(param) = 0) then begin if (ch.tracking = '') then begin ch.sendBuffer('Track whom?'#13#10); exit; end; end else begin vict := findCharWorld(ch, param); if (vict = ch) then begin ch.sendBuffer('You stop looking for tracks.'#13#10); ch.tracking := ''; exit; end; end; act(AT_REPORT,'You begin to look for tracks...',false,ch,nil,nil,TO_CHAR); if (vict <> nil) then ch.tracking := vict.name^; registerTimer(TIMER_TRACK, track_timer, 4, ch, vict, gsn_track); end;