#include "map.h" #include "char.h" #include "game.h" static char const *attacks[] = { "Chop!", "Clang!", "Ouch!", "Thud", "Clink!", "Shriek!", "Slash!", "Ugh!", "Claw!", "Crunch!", "Gnarl!", "Growl!", "Shred!", "Thump!" }; static int pass_key=FALSE; /* C64: (Healing equation?) 4 poke198,0:gd=0:p1=0:l1=0:b1=0:r1=50:s=20-l:gosub208:pokev3,0:ifs<1thens=1 62 ifht<0then114 63 sp=sp+1:ifhtht/th*r1thenht=ht+1:print"(home) ":sp=0 */ static void player_health_add(int id, int health) { list[id].hit+=health; if(list[id].hit>list[id].maxhit) list[id].hit=list[id].maxhit; update_stats (); } static void healing (int id) { int rate, multiplier; if (list[id].fighting || list[id].hit < 0 || paused) return; list[id].healing_time++; multiplier = map_get_spot (list[id].x, list[id].y) == SPOT_TEMPLE ? 1 : 0; multiplier += list[id].amulets_of_healing; multiplier = 1 << (list[id].spells[SPELL_REGENERATION].active + multiplier); rate = 10 * FPS * list[id].hit / (list[id].maxhit * multiplier); if (list[id].hit < list[id].maxhit && list[id].healing_time > rate) { list[id].healing_time = 0; player_health_add(id, 1); } } /* C64: healing potion 60 hp=hp-1:x=int(20*rnd(1)+3*l):ht=ht+x:ifht>ththenht=th 61 gosub113:print"(home)healing potion taken!":gosub182:goto40 */ static int drink_potion(int id) { if (list[id].potions && list[id].hit < list[id].maxhit) { list[id].potions--; player_health_add(id, rnd(0, 19)+3*list[id].current_level); message (FPS * 2, potion, "Healing potion taken!"); return TRUE; } return FALSE; } static void try_lose_map(int id) { int r = rnd (1, 4); (void) id; if (r == 1) { message (FPS * 2, NULL, "Lost your map!"); map_hide_completely (); } } static void monster_step_back (int e) { /* Step back in overlapping mode */ int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1}; int dy[] = { 0, -1, -1, -1, 0, 1, 1, 1}; static int d[] = {0, 1, 2, 3, 4, 5, 6, 7}; int remaining = 8; /* Restore overlapped player. */ map_put_char (list[e].x, list[e].y, 1); while (remaining) { int r = rnd (0, remaining - 1); int rd = d[r]; int x = list[e].x + dx[rd]; int y = list[e].y + dy[rd]; if (map_get_spot (x, y) != SPOT_WALL && !map_get_char (x, y)) { list[e].x += dx[rd]; list[e].y += dy[rd]; break; } remaining--; d[r] = d[remaining]; d[remaining] = rd; } map_put_char (list[e].x, list[e].y, e); } void cancel_fighting (int id) { if (list[id].fighting) { int e = list[id].fighting; /* Weak monsters bring less XP! */ list[e].maxhit = list[e].hit; list[e].fighting = 0; list[e].attacked = 0; list[id].fighting = 0; list[id].attacked = 0; list[id].spells[SPELL_SHIELD].active = 0; if (!extensions_overlapfight) map_put_char (list[e].x, list[e].y, e); } } void player_won (int id) { int e = list[id].fighting; // 298 s1=0:e=e+(s%+h1)*l:bs=bs+int(5*rnd(1)+1):mk=mk+1:k=32 // 299 m%=0:gosub113:print"(home)you vanquished "x$:gosub112 // or // 346 v1=0:s1=0:pokeo,a:e=e+(s%+h1)*l:bs=bs+int(5*rnd(1)+1):mk=mk+1 // 347 print"(home)you have slain "x$:gosub300:w%=1:gosub175 list[id].exp += (list[e].dex + list[e].maxhit)*list[id].current_level; //rnd (m_bs / p_bs, 3 * m_bs / p_bs) if (extensions_balance) { list[id].dex+=rnd(((float)list[e].dex/list[id].dex), 4*((float)list[e].dex/list[id].dex))+1; } else { list[id].dex+=rnd(1, 5); } list[id].slain_foes[0]++; list[id].slain_foes[list[e].type]++; if (list[id].attacked) { message (FPS * 2, victory, "You vanquished %s %s!", char_prefixes[list[e].type][list[e].subtype], char_names[list[e].type]); } else { message (FPS * 2, victory, "You have slain %s %s!", char_prefixes[list[e].type][list[e].subtype], char_names[list[e].type]); } if (list[e].gold) { // 350 gosub113:print"(home)found your"g(v)"gold!!":t=t+g(v):goto274 list[id].gold += list[e].gold; if(extensions_monsteraction) { message (FPS / 2, NULL, "Found %i gold!!", list[e].gold); } else { message (FPS / 2, NULL, "Found your %i gold!!", list[e].gold); } } { int s; int got_stuff = 0; for (s = 0; s < 6; s++) { if (list[e].spells[s].amount) { got_stuff = 1; list[id].spells[s].amount += list[e].spells[s].amount; } } if (got_stuff) message (FPS / 2, NULL, "Found your spells!!"); } if (list[e].exp) { list[id].exp += list[e].exp; message (FPS / 2, NULL, "Regained your experience!!"); } monster_die (e); cancel_fighting (id); if (!extensions_overlapfight) map_put_char (list[id].x, list[id].y, id); } static void fight_action(int e) { int random_sound = rnd (0, 6); if (list[e].type >= CHAR_DIREWOLF) { message_ex(FPS * 1.25, creature[random_sound], 0, 50, 0, "%s", attacks[7 + random_sound]); } else { message_ex(FPS * 1.25, human[random_sound], 0, 50, 0, "%s", attacks[random_sound]); } } static void player_fight (int id) { int e = list[id].fighting; int my_attack, monster_attack; int max_damage; float skill_ratio; update_stats (); /* Assassin is visible during fight. */ if (list[e].type == CHAR_ASSASSIN) { list[e].spells[SPELL_INVISIBILITY].active = 0; /* Redraw */ map_put_char (list[e].x, list[e].y, e); } if (!list[e].dex) { // 307 print"(home)the mage takes your magic spells!!":iv=0:rg=0:tp=0:sh=0:fa=0:lg=0:goto309 // 308 print"(home)the demon drains your experience level!!":e=int(e/2):ifel>1thenel=el-1 if (list[e].type >= CHAR_DIREWOLF) { message (FPS, NULL, "The demon drains your experience level!!"); list[e].exp = list[id].exp / 2; list[id].exp -= list[e].exp; if(!extensions_monsteraction) if (list[id].lev > 1) list[id].lev--; list[e].trapped = 1; list[e].dex++; } else { int s; message (FPS, NULL, "The mage takes your magic spells!!"); for (s = 0; s < 6; s++) { list[e].spells[s].amount = list[id].spells[s].amount; list[id].spells[s].amount = 0; } list[e].trapped = 1; list[e].dex++; } // 309 m%=0:gosub112:gosub300:return if (extensions_monsteraction) { monster_teleport (e); if (!extensions_overlapfight) map_put_char (list[id].x, list[id].y, id); } else monster_die (e); cancel_fighting (id); return; } // C64: 286 x2=s%/bs:h1=h% skill_ratio=(float)list[id].dex/(list[e].dex); //290 h%=h%-int(1/x2*4*l*rnd(1)+1+pl):ifh%<0then298 max_damage = (float)(skill_ratio) * 4 * list[id].current_level; my_attack = rnd (1, max_damage) + list[id].weapon; // C64: 288 ht=ht-int(x2*4*l*rnd(1)+1) skill_ratio=(float)list[e].dex/(list[id].dex); max_damage = (float)skill_ratio * 4 * list[id].current_level; monster_attack = rnd (1, max_damage); /* We are merely defending ourselves. */ if (list[id].attacked) { // 286 x2=s%/bs:h1=h% // 287 ifs1=1then289 // 288 ht=ht-int(x2*4*l*rnd(1)+1) if (!list[id].spells[SPELL_SHIELD].active) { player_health_add(id, -monster_attack); add_hit (list[id].x, list[id].y, -monster_attack); } fight_action(e); // 289 ifd=1andt>0orsf=1thenifx2<.5orx2>1orc=42then294 if (list[e].type < CHAR_DIREWOLF && (list[id].gold || list[id].sword)) { if (list[e].dex > list[id].dex || list[e].dex * 2 < list[id].dex || list[e].type == CHAR_ROGUE) { // 294 gosub113:ifsf=1thensf=0:print"(home)the sword is stolen!!":gosub112:goto296 // 295 d=-1:p=a:print"(home)your gold is stolen!!":gosub112:g(j)=t:t=0:goto386 if (list[id].sword) { list[e].sword = list[id].sword; list[id].sword = 0; message (FPS * 2, NULL, "The sword is stolen!!"); list[e].trapped = 1; if (list[id].current_level == swordlev) { map_put_spot (19, 12, SPOT_SWORD); } } else { message (FPS * 2, NULL, "Your gold is stolen!!"); list[e].gold = list[id].gold; list[id].gold = 0; list[e].trapped = 1; } if (!extensions_overlapfight) monster_step_back (e); cancel_fighting (id); } } if (list[id].fighting) { // 290 h%=h%-int(1/x2*4*l*rnd(1)+1+pl):ifh%<0then298 list[e].hit -= my_attack; add_hit (list[e].x, list[e].y, my_attack); if (list[e].hit < 0) player_won (id); // 291 ifht<-5thengosub113:print"(home)slain by "x$:goto426 else if (list[id].hit < -5) { player_die (id); message (FPS, slain, "Slain by %s %s", char_prefixes[list[e].type][list[e].subtype], char_names[list[e].type]); cancel_fighting(id); } } } else /* We are attacking. */ { // 340 h%=h%-int(1/x*4*l*rnd(1)+1+pl):ifh%<0then346 list[e].hit -= my_attack; if (list[e].dex) { add_hit (list[e].x, list[e].y, my_attack); } if (list[e].hit < 0) { player_won (id); } else { // 341 ifs1=1then344 // 342 ht=ht-int(x*4*l*rnd(1)+1) // 343 ifht<-5thenprint"(home)(rvon) (rvof) thou art slain!":goto426 fight_action(e); if (!list[id].spells[SPELL_SHIELD].active) { player_health_add(id, -monster_attack); add_hit (list[id].x, list[id].y, -monster_attack); if (list[id].hit < -5) { player_die (id); message (FPS, slain, "Thou art slain!"); cancel_fighting (id); } } } } } void player_roll (int *health, int *skill) { int i; /* - Hah! I new it! Initial roll for the player's stats (3d6): 443 fori=1to3:ht=ht+int(6*rnd(1)+1):bs=bs+int(6*rnd(1)+1):next 444 sr=1:th=ht:ep=200:k=32:hp=1:tp=1:t1=100:ql=int(5*rnd(1)+15) - Quest Level is assigned in 'ql' above */ *health = 0; *skill = 0; for (i = 0; i < 3; i++) { *health += rnd (1, 6); *skill += rnd (1, 6); } } int player_create (int x, int y, int health, int skill) { int id = char_create (x, y); list[id].type = CHAR_HERO; list[id].hit = health; list[id].dex = skill; list[id].maxhit = list[id].hit; list[id].next = 200; list[id].potions = 1; list[id].spells[SPELL_TELEPORT].amount = 1; return id; } static void player_treasure (int id) { // 227 r=int(9*rnd(1)+1):onrgoto236,243,228,245,247,247,247,247,247 int w = rnd (1, 9); int x = list[id].x; int y = list[id].y; map_put_spot (x, y, SPOT_FLOOR); switch (w) { case 1: // 236 p1=0:pokev3,peek(v3)and254:print"(home)pit!!...you fell!" // 237 h1=int(10*rnd(1)+l):k=61:pokem,k:pokeo,k:cl=1:gosub148:goto262 // 238 p$="down":p1=1:p2=k:k=62:pt=int(4*rnd(1)+2) // 239 z=pt*p1:l=l+z:pokeo,p2:gosub113:print"(home)climbing the pit..."; message (FPS, pit, "Pit!!... You fell!"); map_put_spot (x, y, SPOT_PIT); map_put_info(x, y, rnd(2, 5)); list[id].trapped = SPOT_PIT; break; case 2: // 243 pokev3,peek(v3)and254:print"(home)ceiling trap!" // 244 h1=int(10*rnd(1)+l):k=59:pokem,k:pokeo,k:gosub156:cl=1:goto262 message (FPS, pit, "Ceiling trap!"); map_put_spot (x, y, SPOT_CEILING); list[id].trapped = SPOT_CEILING; break; case 3: // 228 print"(home)explosion!!":pokes5,10:pokes6,42:pokes3,1:pokeso,12:pokes5+7,10:pokes6+7,42 message (FPS, boom, "Explosion!!"); if (list[id].spells[SPELL_SHIELD].active) { // 234 s1=0:print"(home)shielded from blast!":gosub112 list[id].spells[SPELL_SHIELD].active--; message (FPS, NULL, "Shielded from blast!"); } else { // C64: 233 next:ifs1=0thenht=ht-int(15*rnd(1)+l):cl=1:goto235 int h = rnd (0, 14)+list[1].current_level; player_health_add(id, -h); add_hit (list[id].x, list[id].y, -h); try_lose_map(id); } break; case 4: // 245 print"(home)teleport...":k=32:pokem,k:pokeo,k:gosub144:o=n-d%:pokeo,a:pokeo+cm,1 message (FPS, teleport, "Teleport..."); char_teleport (id); try_lose_map(id); break; case 5: case 6: case 7: case 8: case 9: { // 247 w%=2:gosub175:e=e+int(50*rnd(1)+l):k=32:pokem,k:x=int(15*rnd(1)+1) // 248 onxgoto250,251,250,249,251,252,257,253,254,255,259,252,257,258,260 list[id].exp += rnd (0, 49) + list[id].current_level; w = rnd (1, 15); switch (w) { case 1: case 2: // 250 print"(home)healing potion!!":hp=hp+1:goto274 message (FPS, item, "Healing potion!!"); list[id].potions++; break; case 3: case 4: // 251 print"(home)magic sack!!":bg=bg+1:t1=t1+100:goto274 message (FPS, item, "Magic sack!!"); list[id].sacks++; break; case 5: /* Played some more, and still spent time in the temple healing in level 8. So now you can get amulets, at most one after every 8 levels, and only a 1:2 chance instead of a regeneration spell. The effect is just like a permanent regeneration spell. */ if (extensions_balance && list[id].current_level > 8 * (1 + list[id].amulets_of_healing) && !rnd (0, 2)) { message (FPS, item, "Amulet of Healing!!"); list[id].amulets_of_healing++; } else { // 249 print"(home)regeneration spell!!":rg=rg+1:goto274 message (FPS, item, "Regeneration spell!!"); list[id].spells[SPELL_REGENERATION].amount++; } break; case 6: case 7: // 252 print"(home)shield spell!!":sh=sh+1:goto274 message (FPS, item, "Shield spell!!"); list[id].spells[SPELL_SHIELD].amount++; break; case 8: case 9: // 257 print"(home)teleport spell!!":tp=tp+1:goto274 message (FPS, item, "Teleport spell!!"); list[id].spells[SPELL_TELEPORT].amount++; break; case 10: /* Since I added a healing amulet, thought could as well add a light amulet. This is very unlikely to obtain right now though (one per 15 levels, and 25% chance instead of a spell. The effect is a permanent light spell. */ if (extensions_balance && list[id].current_level > 15 * (1 + list[id].amulets_of_light) && !rnd (0, 3)) { message (FPS, item, "Amulet of Light!!"); list[id].amulets_of_light++; } else { // 253 print"(home)light spell!!":lg=lg+1:goto274 message (FPS, item, "Light spell!!"); list[id].spells[SPELL_LIGHT].amount++; } break; case 11: // 254 print"(home)enchanted weapon!!":pl=pl+1:bs=bs+int(10*rnd(1)+5):goto274 message (FPS, item, "Enchanted weapon!!"); list[id].weapon++; list[id].dex+=rnd(0, 9)+5; break; case 12: // 255 x=int(8*rnd(1)+l+3):print"(home)map to"x"th level!!" // 256 tm=tm+1:t%(tm)=x:goto274 { int m = list[id].current_level + rnd (3, 10); if(m==list[id].current_level) { message(FPS, item, "Treasure Map!!"); map_seen (20, 12, 20); } else { message (FPS, item, "Map to %ith level!!!", m); list[id].map |= (1 << m); } break; } case 13: // 259 print"(home)invisibility spell!!":iv=iv+1:goto274 message (FPS, item, "Invisibility spell!!"); list[id].spells[SPELL_INVISIBILITY].amount++; break; case 14: // 258 print"(home)drift spell!!":fa=fa+1:goto274 message (FPS, item, "Drift spell!!"); list[id].spells[SPELL_DRIFT].amount++; break; case 15: // 260 print"(home)beacon!!":be=be+1:goto274 message (FPS, item, "Beacon!!"); list[id].beacons++; break; } break; } } } static void climb_pit(int id) { int x = list[id].x; int y = list[id].y; int downsteps = map_get_info (x, y); /* C64: 238 p$="down":p1=1:p2=k:k=62:pt=int(4*rnd(1)+2) 239 z=pt*p1:l=l+z:pokeo,p2:gosub113:print"(home)climbing the pit..."; 240 pokev3,peek(v3)and254:w1=int(2*rnd(1)+1):gosub171:y=int(2*rnd(1)) 241 ify=1thenprint"you fell!":h1=int(10*rnd(1)+3*pt+l):gosub148:goto261 */ list[id].current_level += downsteps; message (FPS, climb, "Climbing the pit..."); if (!rnd (0, 1)) { list[id].trapped = SPOT_PIT; message (0, pit, NULL); } map_enter (SPOT_ROPE, downsteps); } static void player_action (int id) { int x = list[id].x; int y = list[id].y; int spot; /* During fighting, try to teleport away. 302 iftp>0then305 303 ifsh>0ands1=0thensh=sh-1:s1=1:gosub113:print"(home)thy shield is in - This is only if attacked - Shield will be used if there's no teleport */ if (list[id].attacked) { if(!spell_cast (id, SPELL_TELEPORT)) { if(!spell_cast(id, SPELL_SHIELD)) { play_sample (ding, 250, 128, 1000, 0); return; } } else { // So that we can't cast both spells by accident list[id].attacked=0; } return; } if (list[id].trapped==SPOT_PIT) { if(!spell_cast (id, SPELL_DRIFT)) play_sample (ding, 250, 128, 1000, 0); return; } else if (list[id].trapped==SPOT_CEILING) { if(!spell_cast (id, SPELL_TELEPORT)) play_sample (ding, 250, 128, 1000, 0); return; } spot=map_get_spot (x, y); if(paused) { if(spot==SPOT_FLOOR) { play_sample (ding, 250, 128, 1000, 0); pass_key=TRUE; } return; } switch (spot) { default: play_sample (ding, 250, 128, 1000, 0); pass_key=TRUE; break; case SPOT_DOWN: list[id].current_level++; message (FPS, down, "You go down the stairs."); map_enter (SPOT_UP, 1); break; case SPOT_UP: if (list[id].current_level == 1) { if (swordrun && list[id].sword) { // 111 print"(clr)(down)(down)(down)(down)(down)(down)(down)(down)(down)(down) your quest is complete!!":gosub201:goto412 message (FPS * 4, intro, "Your quest is complete!!"); won = 1; } else { message (FPS, NULL, "Not without the Sword of Fargoal!"); } } else { list[id].current_level--; message (FPS, up, "You go up the stairs."); map_enter (SPOT_DOWN, 1); } break; case SPOT_ROPE: { int upsteps = map_get_info (x, y); list[id].current_level -= upsteps; message (FPS, climb, "Climbing the rope..."); map_enter (SPOT_PIT, upsteps); break; } case SPOT_PIT: { climb_pit(id); break; } case SPOT_BEACON: // 92 ifk=44thenpokeo,k:k=38:o=b3:pokeo,a:pokeo+cm,1:gosub108:gosub146:gosub113:goto117 message (FPS, teleport, NULL); char_transfer_to (id, temple_x, temple_y); break; case SPOT_TREASURE: player_treasure (id); break; } } static void player_in_trap (int id) { int x = list[id].x; int y = list[id].y; int s = map_get_spot (x, y); if (s == SPOT_PIT || s == SPOT_ROPE) { if (!list[id].spells[SPELL_DRIFT].active) { int h; if (s == SPOT_PIT) { // 237 h1=int(10*rnd(1)+l):k=61:pokem,k:pokeo,k:cl=1:gosub148:goto262 h = rnd(0, 9)+list[id].current_level; message (FPS, human[0], NULL); } else { // 241 ify=1thenprint"you fell!":h1=int(10*rnd(1)+3*pt+l):gosub148:goto261 int upsteps = map_get_info (x, y); h = rnd (0, 9) + 3 * upsteps + list[id].current_level; message (FPS, human[0], "You fell!"); } player_health_add(id, -h); add_hit (list[id].x, list[id].y, -h); } else { list[id].spells[SPELL_DRIFT].active--; message (FPS, NULL, "like a feather..."); } } /* Crushing ceiling. */ if (s == SPOT_CEILING) { if (!list[id].spells[SPELL_TELEPORT].active) { /* C64: 244 h1=int(10*rnd(1)+l):k=59:pokem,k:pokeo,k: gosub156:cl=1:goto262 */ int h = rnd (0, 9)+list[id].current_level; message (FPS, crunch, NULL); player_health_add(id, -h); add_hit (list[id].x, list[id].y, -h); try_lose_map(id); } else { list[id].spells[SPELL_TELEPORT].active--; char_teleport (1); message (FPS, NULL, "Teleport to safety!"); } } } void player_try_levelup (int id) { /* C64: Level up 119 ep=ep*2:el=el+1:th=th+int(15*rnd(1)+5):bs=bs+int(10*rnd(1)+1) - Implemented */ if (list[id].exp >= list[id].next) { float percentage = (float)list[id].hit / (float)list[id].maxhit; list[id].lev++; list[id].maxhit += rnd (1, 15)+4; list[id].dex += rnd (1, 10); if (extensions_balance) list[id].hit = percentage * list[id].maxhit + 0.5; list[id].next *= 2; message (FPS, levelup, "Gained a level!"); //printf ("maxhit = %i skill = %i\n", list[id].maxhit, list[id].dex); } } void player_die (int id) { (void) id; gameover = 1; spiral_map = MAP_W * MAP_H / 2; } void player_process (int id) { int x = list[id].x; int y = list[id].y; int i; /* Keyboard state. */ int dir_x = 0; int dir_y = 0; #if defined(_DEBUG) || defined(DEBUGMODE) if (key[KEY_0]) { player_health_add(id, -list[id].hit);; } if (key[KEY_1]) { list[id].spells[SPELL_SHIELD].amount=1; list[id].spells[SPELL_TELEPORT].amount=1; list[id].spells[SPELL_DRIFT].amount=1; list[id].spells[SPELL_LIGHT].amount=1; list[id].spells[SPELL_REGENERATION].amount=1; list[id].spells[SPELL_INVISIBILITY].amount=1; list[id].beacons++; list[id].potions++; list[id].gold+=50; list[id].dex=400; list[id].maxhit++; list[id].hit=list[id].maxhit; update_stats(); } if (key[KEY_2]) { list[id].current_level=20; list[id].hit=list[id].maxhit; update_stats(); } if (key[KEY_3]) { map_seen (20, 12, 20); } if (key[KEY_4]) { list[id].sword = 1; swordrun = SWORD_TIME; } if (key[KEY_5]) { list[id].amulets_of_healing = 1; list[id].amulets_of_light = 1; update_stats(); } if (key[KEY_6]) { list[id].amulets_of_healing = 0; list[id].amulets_of_light = 0; update_stats(); } #endif if (check_key_ex(KEY_LEFT, TRUE)) { dir_x = -1; } if (check_key_ex(KEY_RIGHT, TRUE)) { dir_x = 1; } if (check_key_ex(KEY_UP, TRUE)) { dir_y = -1; } if (check_key_ex(KEY_DOWN, TRUE)) { dir_y = 1; } /* Check spell keys. */ for (i = 0; i < 6; i++) { static int spellkeys[] = { KEY_I, KEY_R, KEY_T, KEY_S, KEY_L, KEY_D }; if (check_key (spellkeys[i])) { if (!spell_cast (id, i)) play_sample (ding, 250, 128, 1000, 0); } } if (check_key (KEY_B)) { // 54 ifa$="+"andbe>0andb1=0thenbe=be-1:b1=1:k=44:b2=o:pokeo+d%,k:gosub113:print"(home)thy beacon is placed!":gosub150:goto40 if (list[id].beacons && list[id].beaconx == 0 && list[id].beacony == 0) { if (map_get_spot (x, y) == SPOT_FLOOR) { map_put_spot (x, y, SPOT_BEACON); list[id].spells[SPELL_INVISIBILITY].active++; list[id].beacons--; list[id].beaconx = x; list[id].beacony = y; message (FPS, beacon, "Thy beacon is placed!"); } else { message (FPS, ding, "Cannot place beacon here"); } } else play_sample (ding, 250, 128, 1000, 0); } if (check_key (KEY_H)) { if (!drink_potion(id)) { play_sample (ding, 250, 128, 1000, 0); } } if (check_key (KEY_LCONTROL) || check_key (KEY_RCONTROL) || check_key (KEY_SPACE) || check_key (KEY_ENTER)) { player_action (id); } if (check_key (KEY_O)) { // 121 gosub113:ifl1=1thenl1=2:print"(home)light off":gosub112:goto42 // 122 l1=1:gosub211:print"(home)light on":gosub112:goto42 if (list[id].spells[SPELL_LIGHT].active) { list[id].spells[SPELL_LIGHT].active = -list[id].spells[SPELL_LIGHT].active; if (list[id].spells[SPELL_LIGHT].active > 0) message (FPS, NULL, "Light on"); if (list[id].spells[SPELL_LIGHT].active < 0) message (FPS, NULL, "Light off"); } else play_sample (ding, 250, 128, 1000, 0); } if (check_key (KEY_G)) { // 124 ifgd>9ork<>32then41 // 125 gd=gd+1:k=60:pokeo+d%,k:g%(gd)=t:l%(gd)=o:gosub113 // 126 print"(home)hiding"t"gold pieces":t=0:gosub112:goto42 if (list[id].gold) { if (map_get_spot (x, y) == SPOT_FLOOR) { message (FPS, NULL, "Hiding %i gold pieces", list[id].gold); map_put_spot (x, y, SPOT_STASH); map_put_info (x, y, list[id].gold); list[id].gold = 0; } else { message (FPS, ding, "Cannot bury gold here"); } } else play_sample (ding, 250, 128, 1000, 0); } healing (id); /* Game is currently paused. */ if (paused) { paused--; char_move (id, 0, 0); if (paused == 0) { if (list[id].trapped) { player_in_trap(id); list[id].trapped = 0; } } } else /* Not paused. */ { if (!extensions_nomonsterpause) { if(!global_steps) { dir_x = dir_y = 0; } } // See if player is trying to escape, and was not attacked if (!list[id].attacked) { char_move (id, dir_x, dir_y); } if (!paused && !list[id].step) { // 114 ifhp>0then60 // 115 gosub113:print"(home)(rvon) (rvof) you died!!":goto426 /* Teleport spell? */ if (list[id].spells[SPELL_TELEPORT].active) { char_teleport (id); cancel_fighting (id); list[id].spells[SPELL_TELEPORT].active--; } /* Dead? */ if (list[id].hit < 0) { if (!drink_potion(id)) { player_die (id); message (FPS, slain, "You died!!"); return; } } if (list[id].fighting) player_fight (id); } player_try_levelup (id); } } void player_leave (int id) { int x = list[id].x; int y = list[id].y; switch (map_get_spot (x, y)) { default: break; case SPOT_BEACON: list[id].spells[SPELL_INVISIBILITY].active--; update_stats(); break; } } void player_change_position (int id) { int x = list[id].x; int y = list[id].y; int r = 1 + list[id].spells[SPELL_LIGHT].active + list[id].amulets_of_light; int spot; if (r < 1) r = 1; map_seen (x, y, r); play_sample (step, 250, 128, 1000, 0); if (extensions_nomonsterpause && global_steps) { global_steps--; stepcount = (extensions_speed ? FPS : FPS*2); } spot=map_get_spot (x, y); // TODO: if Pass key, clear key and return if(pass_key&&spot!=SPOT_FLOOR&&spot!=SPOT_VOID) { pass_key=FALSE; return; } switch (spot) { default: break; case SPOT_TREASURE: if(!extensions_controls) player_treasure (id); break; case SPOT_DOWN: message (FPS / 2, down, "Stairs going down"); break; case SPOT_UP: message (FPS / 2, up, "Stairs going up"); break; case SPOT_PIT: if(extensions_controls) message (FPS / 2, NULL, "Pit!"); else climb_pit(id); break; case SPOT_ROPE: message (FPS / 2, NULL, "Climbable pit above!"); break; case SPOT_CEILING: message (FPS / 2, NULL, "hole in the ceiling!"); break; case SPOT_BEACON: message (FPS * 2, beacon, "Swirling mists surround you!"); /* Get invisible on beacon. */ list[id].spells[SPELL_INVISIBILITY].active++; break; case SPOT_SWORD: // 94 gosub113:print"(home)the sword of fargoal!!":gosub201:sf=1:k=32:pokem,k:ift2=0thene=e*2:t2=ti // 95 goto274 list[id].sword++; if (swordrun == 0) { list[id].exp *= 2; swordrun = SWORD_TIME; } message (FPS * 4, intro, "The Sword of Fargoal!!"); map_put_spot (x, y, SPOT_FLOOR); break; case SPOT_GOLD: { // 216 y=int(20*rnd(1)+10*l):print"(home)treasure: "y"gp's":gosub165:ift+y>t1then218 // 217 t=t+y:k=32:pokem,k:goto40 // 218 ifgd>9then40 // 219 gd=gd+1:k=60:pokem,k:g%(gd)=t+y-t1:l%(gd)=o:ift=t1then221 // 220 t=t1:print"(home)can't carry more gold":goto274 // 221 print"(home)hiding the gold ":goto274 int max = 100 + list[id].sacks * 100; int g = 10 * list[id].current_level + rnd (0, 19); //if(extensions_controls && max <= list[id].gold) // break; message (FPS, gold, "Treasure: %i GP's", g); if (list[id].gold + g <= max) { map_put_spot (x, y, SPOT_FLOOR); list[id].gold += g; } else { map_put_spot (x, y, SPOT_STASH); map_put_info (x, y, list[id].gold + g - max); if (list[id].gold < max) { list[id].gold= max; message (FPS/2, NULL, "Can't carry more gold"); } else { message (FPS/2, NULL, "Hiding the gold"); } } break; } case SPOT_STASH: { // 222 print"(home)hidden treasure!!":gosub165:forj=1togd:ifo=l%(j)thenv=j:j=gd // 223 next // 224 z=g%(v):ift+z>t1then226 // 225 t=t+z:k=32:pokem,k:goto40 // 226 g%(v)=t+z-t1:t=t1:gosub113:print"(home)gold too heavy":goto274 int max = 100 + list[id].sacks * 100; int g = map_get_info (x, y); if(max<=list[id].gold) break; message (FPS / 2, gold, "Hidden Treasure!!"); if (list[id].gold + g <= max) { list[id].gold += g; map_put_spot (x, y, SPOT_FLOOR); } else { map_put_info (x, y, list[id].gold + g - max); list[id].gold= max; message (FPS/2, NULL, "Gold too heavy"); } break; } case SPOT_TEMPLE: if (list[id].gold) { message (FPS, sacrifice, "Sacrifice of gold!"); list[id].exp += list[id].gold; if (extensions_balance) { { list[id].sacrificed_gold+=list[id].gold; if(list[id].sacrificed_gold>=TEMPLE_GOLD && list[id].hit