void do_lavablast(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_TANARRI)) { send_to_char("Huh?\n\r",ch); return; } if (!IS_SET(ch->pcdata->powers[TANARRI_POWER], TANARRI_LAVA)) { send_to_char("Perhaps you should learn that power first.\n\r",ch); return; } if (ch->mana < 1000 || ch->move < 1000) { send_to_char("Your not up to it, you ain't got the fire in ya.\n\r",ch); return; } if ((victim = ch->fighting) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } ch->mana -= 1000; ch->move -= 1000; one_hit(ch,victim,gsn_magma,1); one_hit(ch,victim,gsn_magma,1); one_hit(ch,victim,gsn_magma,1); if (!IS_AFFECTED(victim, AFF_FLAMING)) SET_BIT(victim->affected_by, AFF_FLAMING); WAIT_STATE(ch,18); return; }
void do_slide(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_SAMURAI)) { send_to_char("Huh?\n\r",ch); return; } if (!IS_SET(ch->pcdata->powers[SAMURAI_MARTIAL], SAM_SLIDE)) { send_to_char("You need to learn that combo first.\n\r", ch); return; } if (ch->pcdata->powers[SAMURAI_FOCUS] > 40) { send_to_char("You are to exhausted.\n\r",ch); return; } if ((victim = ch->fighting) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } ch->pcdata->powers[SAMURAI_FOCUS] += 1; act("$n slides into a better fighting position, hitting $N while $e passes.",ch,NULL,victim,TO_NOTVICT); act("You slide into a better fighting position, hitting $N while you pass $E.",ch,NULL,victim,TO_CHAR); act("$n moves past you, lightning fast and strikes you before you can react.",ch,NULL,victim,TO_VICT); one_hit(ch, victim, gsn_lightningslash, 1); check_samuraiattack(ch, victim); WAIT_STATE(ch, 12); return; }
/* * Do one group of attacks. */ void multi_hit( CHAR_DATA *ch, CHAR_DATA *victim, int dt ) { /* decrement the wait */ if (ch->desc == NULL) ch->wait = UMAX(0,ch->wait - PULSE_VIOLENCE); if (ch->desc == NULL) ch->daze = UMAX(0,ch->daze - PULSE_VIOLENCE); /* no attacks for stunnies -- just a check */ if (ch->position < P_REST) return; if (IS_NPC(ch)) { mob_hit(ch,victim,dt); return; } one_hit( ch, victim, dt ); if (ch->fighting != victim) return; if ( ch->fighting != victim || dt == gsn_backstab ) return; return; }
void do_countermove(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_SAMURAI)) { send_to_char("Huh?\n\r",ch); return; } if (!IS_SET(ch->pcdata->powers[SAMURAI_MARTIAL], SAM_COUNTERMOVE)) { send_to_char("You need to learn that combo first.\n\r", ch); return; } if (ch->pcdata->powers[SAMURAI_FOCUS] > 40) { send_to_char("You are to exhausted.\n\r",ch); return; } if ((victim = ch->fighting) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } ch->pcdata->powers[SAMURAI_FOCUS] += 8; act("$n strikes out at $N before $E can even get a weapon out to defend $Mself.",ch,NULL,victim,TO_NOTVICT); act("You cut $N with a lightning fast attack.",ch,NULL,victim,TO_CHAR); act("$n attacks with a flurry of lightning fast attacks, one of them scores a hit.",ch,NULL,victim,TO_VICT); one_hit(ch, victim, gsn_lightningslash, 1); check_samuraiattack(ch, victim); WAIT_STATE(ch, 12); return; }
void do_block(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_SAMURAI)) { send_to_char("Huh?\n\r",ch); return; } if (!IS_SET(ch->pcdata->powers[SAMURAI_MARTIAL], SAM_BLOCK)) { send_to_char("You need to learn that combo first.\n\r", ch); return; } if (ch->pcdata->powers[SAMURAI_FOCUS] > 40) { send_to_char("You are to exhausted.\n\r",ch); return; } if ((victim = ch->fighting) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } ch->pcdata->powers[SAMURAI_FOCUS] += 4; act("$n blocks $N's simpleminded attack and strikes back with a perfect attack.",ch,NULL,victim,TO_NOTVICT); act("You block $N's simple attack and return with one of your own design.",ch,NULL,victim,TO_CHAR); act("$n blocks your attack, and strikes back before you get a chance to react.",ch,NULL,victim,TO_VICT); one_hit(ch, victim, gsn_lightningslash, 1); check_samuraiattack(ch, victim); WAIT_STATE(ch, 12); return; }
void do_sidestep(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_SAMURAI)) { send_to_char("Huh?\n\r",ch); return; } if (!IS_SET(ch->pcdata->powers[SAMURAI_MARTIAL], SAM_SIDESTEP)) { send_to_char("You need to learn that combo first.\n\r", ch); return; } if (ch->pcdata->powers[SAMURAI_FOCUS] > 40) { send_to_char("You are to exhausted.\n\r",ch); return; } if ((victim = ch->fighting) == NULL) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } ch->pcdata->powers[SAMURAI_FOCUS] += 2; act("$n sidesteps $N's attack and scores a hit.",ch,NULL,victim,TO_NOTVICT); act("You sidestep $N's attack, and scores a counterattack before $E can react.",ch,NULL,victim,TO_CHAR); act("$n sidesteps your feeble attempt to get near $m and strikes back at you.",ch,NULL,victim,TO_VICT); one_hit(ch, victim, gsn_lightningslash, 1); check_samuraiattack(ch, victim); WAIT_STATE(ch, 12); return; }
void do_sinsofthepast( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; argument = one_argument( argument, arg ); if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_ANGEL)) { send_to_char("Huh?\n\r",ch); return; } if (ch->pcdata->powers[ANGEL_JUSTICE] < 3) { send_to_char("Your not ready to punish the sinners.\n\r",ch); return; } if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char("They are not here.\n\r", ch); return; } /* if (IS_NPC(victim)) { send_to_char("Not on mobiles.\n\r",ch); return; }*/ if (is_safe(ch,victim)) return; if (victim == ch) { send_to_char("That doesn't seem like a good idea.\n\r",ch); return; } send_to_char("#RYou burn them with the fires of hell!#n\n\r",ch); if (!IS_AFFECTED(victim, AFF_FLAMING)) SET_BIT(victim->affected_by, AFF_FLAMING); send_to_char("#LTheir body is wrecked by poison!#n\n\r",ch); if (!IS_AFFECTED(victim, AFF_POISON)) SET_BIT(victim->affected_by, AFF_POISON); send_to_char("#CGod's fury upon them for they have truly sinned!!!#n\n\r",ch); one_hit(ch,victim, gsn_wrathofgod,1); one_hit(ch,victim, gsn_wrathofgod,1); one_hit(ch,victim, gsn_wrathofgod,1); one_hit(ch,victim, gsn_wrathofgod,1); WAIT_STATE(ch,12); return; }
void do_infernal(CHAR_DATA *ch, char *argument) { CHAR_DATA *ich; CHAR_DATA *ich_next; if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_TANARRI) && !IS_CLASS(ch, CLASS_LICH)) { send_to_char("Huh?\n\r",ch); return; } if (!IS_SET(ch->pcdata->powers[TANARRI_POWER], TANARRI_FLAMES) && IS_CLASS(ch, CLASS_TANARRI)) { send_to_char("You don't have that power yet.\n\r",ch); return; } if (ch->pcdata->powers[CON_LORE] < 2 && IS_CLASS(ch, CLASS_LICH)) { send_to_char("You don't have that power yet.\n\r",ch); return; } if (ch->mana < 2000) { if (IS_CLASS(ch, CLASS_TANARRI)) send_to_char("You need more mana to summon the infernal flames of the abyss.\n\r",ch); else send_to_char("Not enough mana.\n\r",ch); return; } if (IS_CLASS(ch, CLASS_TANARRI)) send_to_char("You summon the infernal flames of the abyss.\n\r",ch); else send_to_char("You mutter an incantation and a fireball flies from your hands.\n\r",ch); ich_next = ch->in_room->people; ich = ich_next; while (ich_next != NULL) { ich_next = ich->next_in_room; if (ich != ch) { if (is_safe(ch,ich)) break; one_hit(ch,ich,gsn_fireball,1); one_hit(ch,ich,gsn_fireball,1); } ich = ich_next; } ch->mana -= 2000; WAIT_STATE(ch, 12); return; }
void do_booming(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; argument = one_argument( argument, arg ); if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_TANARRI)) { send_to_char("Huh?\n\r",ch); return; } if (!IS_SET(ch->pcdata->powers[TANARRI_POWER], TANARRI_BOOMING)) { send_to_char("You don't have that power yet.\n\r",ch); return; } if ((victim = get_char_room(ch, arg)) == NULL) { send_to_char("They are not here.\n\r", ch); return; } if (IS_NPC(victim)) one_hit(ch,victim, gsn_booming, 1); else { if (victim == ch) { send_to_char("That doesn't seem like a good idea.\n\r",ch); return; } one_hit(ch,victim, gsn_booming, 1); if (victim->position == POS_FIGHTING && number_range(1,4)==2) { send_to_char("Your booming voice stuns your opponent.\n\r",ch); send_to_char("The pain is to much, and you drop to the ground.\n\r",victim); stop_fighting(victim,TRUE); victim->position = POS_STUNNED; } } WAIT_STATE(ch,12); return; }
void do_stuntubes( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; if ( IS_NPC(ch) ) return; if ( !IS_CLASS(ch, CLASS_DROID) ) { send_to_char("Huh?\n\r", ch); return; } if (ch->pcdata->powers[CYBORG_BODY] < 5 || ch->pcdata->powers[CYBORG_LIMBS] < 5 ) { send_to_char("You need level 5 implants on your legs and body to use this.\n\r",ch); return; } if (ch->move < 1000) { stc("You need 1000 move to do that.\n\r",ch); return; } if ( ( victim = ch->fighting ) == NULL ) { send_to_char( "You aren't fighting anyone.\n\r", ch ); return; } WAIT_STATE( ch, 12); ch->move -= 1000; one_hit(ch,victim,gsn_stuntubes,1); one_hit(ch,victim,gsn_stuntubes,1); one_hit(ch,victim,gsn_stuntubes,1); if (!IS_AFFECTED(victim, AFF_POISON)) SET_BIT(victim->affected_by, AFF_POISON); if (!IS_AFFECTED(victim, AFF_FLAMING)) SET_BIT(victim->affected_by, AFF_FLAMING); return; }
void do_tornado(CHAR_DATA *ch, char *argument) { CHAR_DATA *ich; CHAR_DATA *ich_next; if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_TANARRI)) { send_to_char("Huh?\n\r",ch); return; } if (!IS_SET(ch->pcdata->powers[TANARRI_POWER], TANARRI_TORNADO)) { send_to_char("You don't have that power yet.\n\r",ch); return; } if (ch->mana < 1500) { send_to_char("You need more mana to summon a storm.\n\r",ch); return; } send_to_char("You summon a supernatural storm.\n\r",ch); ich_next = ch->in_room->people; ich = ich_next; while (ich_next != NULL) { ich_next = ich->next_in_room; if (ich != ch && IS_AFFECTED(ich, AFF_FLYING)) { if (is_safe(ch,ich)) break; one_hit(ch,ich,gsn_lightning,1); one_hit(ch,ich,gsn_lightning,1); } ich = ich_next; } ch->mana -= 1500; WAIT_STATE(ch, 12); return; }
void do_earthquake(CHAR_DATA *ch, char *argument) { CHAR_DATA *ich; CHAR_DATA *ich_next; if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_TANARRI)) { send_to_char("Huh?\n\r",ch); return; } if (!IS_SET(ch->pcdata->powers[TANARRI_POWER], TANARRI_EARTHQUAKE)) { send_to_char("You don't have that power yet.\n\r",ch); return; } if (ch->mana < 1000) { send_to_char("You need more mana to summon an earthquake.\n\r",ch); return; } send_to_char("You summon an earthquake.\n\r",ch); ich_next = ch->in_room->people; ich = ich_next; while (ich_next != NULL) { ich_next = ich->next_in_room; if (ich != ch && !IS_AFFECTED(ich, AFF_FLYING)) { if (is_safe(ch,ich)) break; one_hit(ch,ich,32,1); } ich = ich_next; } ch->mana -= 1000; WAIT_STATE(ch, 12); return; }
void do_chaos( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; AFFECT_DATA af; int chaos, dam; char arg[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; argument = one_argument( argument, arg ); if (IS_NPC(ch)) return; if (!IS_CLASS(ch, CLASS_WIZARD)) { send_to_char("Huh?\n\r",ch); return; } if (ch->pcdata->stats[WL_SPELLS] < 6) { send_to_char("Huh?\n\r",ch); return; } if ( arg[0] == '\0') { send_to_char( "#RCast chaos orb on whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They are not here.\n\r", ch ); return; } if (is_safe(ch, victim)) { stc("You cannot attack them.\n\r",ch); return; } if (ch->mana < 5000) { stc("You do not ave the required 5000 mana.\n\r",ch); return; } chaos = number_range(1, 6); act("#r$n#0 begins chanting dark words, summoning forth a sphere of #rc#lh#pa#go#cs#0 to hurl at #r$N!#n", ch, NULL, victim, TO_NOTVICT); sprintf( buf, "#0You summon forth a perfect sphere of #rc#lh#pa#go#cs#0 and hurl it at #r$N!#n\n\r"); act(buf, ch, NULL, victim, TO_CHAR); sprintf( buf, "#r$n#0 summons forth a perfect sphere of #rc#lh#pa#go#cs#0 and hurls it at you!#n\n\r"); act(buf, ch, NULL, victim, TO_VICT); if (chaos == 1 || chaos == 6) { stc("The sphere explodes in a shower of #Ggreen bubbles#n.\n\r",victim); stc("Your sphere explodes in a shower of #Ggreen bubbles#n.\n\r",ch); if ( IS_AFFECTED(victim, AFF_POISON)) return; af.type = gsn_poison; af.duration = chaos * 10; af.location = APPLY_STR; af.modifier = 0 - number_range(1,3); af.bitvector = AFF_POISON; affect_join( victim, &af ); WAIT_STATE(victim, number_range(5, 20)); send_to_char( "#GYou are poisoned!#n\n\r", victim ); } else if (chaos == 2 || chaos == 7 ) { stc("The sphere explodes, forming a #yyellow haze#n.\n\r",victim); stc("Your sphere explodes, forming a #yyellow haze#n.\n\r",ch); if ( IS_AFFECTED(victim, AFF_BLIND)) { af.type = gsn_blindness; af.location = APPLY_HITROLL; af.modifier = -4; af.duration = chaos * 10; af.bitvector = AFF_BLIND; affect_to_char( victim, &af ); WAIT_STATE(victim, number_range(5, 15)); send_to_char( "#yYou are blinded!#n\n\r", victim ); } else { stc("They are already blinded.\n\r",ch); } } else if (chaos == 3 || chaos == 8) { stc("The sphere explodes in a shower of #Rred flames#n.\n\r",victim); stc("Your sphere explodes in a shower of #Rred flames#n.\n\r",ch); WAIT_STATE(victim, number_range(5, 20)); SET_BIT(victim->affected_by, AFF_FLAMING); } else if (chaos == 4 || chaos == 9) { dam = number_range(3750, 7500); sprintf(buf,"The sphere explodes in a scattering of #Lblue sparks#n. #R[#y%d#R]#n\n\r", dam); stc( buf, victim); sprintf(buf,"Your sphere explodes in a scattering of #Lblue sparks#n. #R[#y%d#R]#n\n\r", dam); stc( buf, ch); WAIT_STATE(victim, number_range(5, 8)); hurt_person(ch, victim, dam); } else if (chaos == 5 ) { stc("The sphere dissipates before it hits you#n.\n\r",victim); stc("Your sphere dissipates shortly after casting#n.\n\r",ch); } one_hit(ch,victim, gsn_wrathofgod,1); one_hit(ch,victim, gsn_wrathofgod,1); WAIT_STATE(ch, 4); ch->mana -= 5000; if (victim->hit < -10) victim->hit = -10; return; }
void GAMECONTROLLER::tick() { // do info message every 10 minutes if(server_tick()%(50*10*60) == 0) { game.send_chat_target(-1, "-------------------------"); game.send_chat_target(-1, "Buy Mod - 0.1"); game.send_chat_target(-1, "by ©Bobynator and ©KaiTee"); game.send_chat_target(-1, "/cmdlist - see all commands"); game.send_chat_target(-1, "/info - see aim of the game"); game.send_chat_target(-1, "-------------------------"); } // inactivity check if(!game.world.paused) for(int i = 0; i < MAX_CLIENTS; i++) if(game.players[i]) if(server_tick()%server_tickspeed() == 0 && game.players[i]->last_input != -1 && server_tick() - game.players[i]->last_input >= 120 * server_tickspeed()) if(server_tick() - game.players[i]->last_input >= 120 * server_tickspeed()) { game.players[i]->set_team(-1); // set him to spectator game.send_chat_target(i, "Inactivity Check: Are you still there?"); //portal ftw ;D } // event stuff // TODO: write event over stuff smarter! if(slow_tick > 0) slow_tick--; if(slow_tick == 0) { console_execute_line("tune_reset"); slow_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(speed_tick > 0) speed_tick--; if(speed_tick == 0) { console_execute_line("tune_reset"); speed_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(x2_tick > 0) x2_tick--; if(x2_tick == 0) { x2_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(one_hit_tick > 0) one_hit_tick--; if(one_hit_tick == 0) { one_hit_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(web_tick > 0) web_tick--; if(web_tick == 0) { web_tick = -1; game.send_broadcast("EVENT OVER!", -1); } if(server_tick()%(50*60*60) == 0 && !is_cup) { int Event = 1+(rand()%(5-1+1)); if(Event == 1) slowmotion(5); else if(Event == 2) x2(2); else if(Event == 3) one_hit(1); else if(Event == 4) speedmotion(3); else if(Event == 5) spider_web(4); } // do warmup if(warmup) { warmup--; if(!warmup) startround(); } // do potcount int enter_players = 0; if(is_cup) for(int i = 0; i < MAX_CLIENTS; i++) if(game.players[i]) { if(game.players[i]->enter_game == true) enter_players++; } if(potcount < 1 && is_cup && game_over_tick == -1) { if(server_tick()%(50*6) == 0 && enter_players > 1 && jackpot > 0) { char buf[512]; str_format(buf, sizeof(buf), "Jackpot: %d $", jackpot); game.send_broadcast(buf, -1, true); } if(enter_players == 1) { endround(); } } if(potcount > 0 && is_cup) { potcount--; char buf[512]; str_format(buf, sizeof(buf), "Jackpot: %d $ | Join-Time: %d", jackpot, potcount/50); for(int i = 0; i < MAX_CLIENTS; i++) { if(game.players[i]) { if(game.players[i]->broadcast_count < 1) game.send_broadcast(buf, i, true); } } } if(potcount == 0 && is_cup) { if(enter_players >= 2) { game.send_broadcast("Game Start!", -1); resetgame(); potcount--; char buf[512]; str_format(buf, sizeof(buf), "sv_scorelimit %d", enter_players*5); console_execute_line(buf); // start game round_start_tick = server_tick(); sudden_death = 0; game_over_tick = -1; game.world.paused = false; teamscore[0] = 0; teamscore[1] = 0; unbalanced_tick = -1; force_balanced = false; } else do_potcount(16); } if(game_over_tick != -1) { // game over.. wait for restart if(server_tick() > game_over_tick+server_tickspeed()*10) { cyclemap(); startround(); round_count++; } } // do team-balancing if (is_teamplay() && unbalanced_tick != -1 && server_tick() > unbalanced_tick+config.sv_teambalance_time*server_tickspeed()*60) { dbg_msg("game", "Balancing teams"); int t[2] = {0,0}; int tscore[2] = {0,0}; for(int i = 0; i < MAX_CLIENTS; i++) { if(game.players[i] && game.players[i]->team != -1) { t[game.players[i]->team]++; tscore[game.players[i]->team]+=game.players[i]->score; } } // are teams unbalanced? if(abs(t[0]-t[1]) >= 2) { int m = (t[0] > t[1]) ? 0 : 1; int num_balance = abs(t[0]-t[1]) / 2; do { PLAYER *p = 0; int pd = tscore[m]; for(int i = 0; i < MAX_CLIENTS; i++) { if(!game.players[i]) continue; // remember the player who would cause lowest score-difference if(game.players[i]->team == m && (!p || abs((tscore[m^1]+game.players[i]->score) - (tscore[m]-game.players[i]->score)) < pd)) { p = game.players[i]; pd = abs((tscore[m^1]+p->score) - (tscore[m]-p->score)); } } // move the player to other team without losing his score // TODO: change in player::set_team needed: player won't lose score on team-change int score_before = p->score; p->set_team(m^1); p->score = score_before; p->respawn(); p->force_balanced = true; } while (--num_balance); force_balanced = true; } unbalanced_tick = -1; } // update browse info int prog = -1; if(config.sv_timelimit > 0) prog = max(prog, (server_tick()-round_start_tick) * 100 / (config.sv_timelimit*server_tickspeed()*60)); if(config.sv_scorelimit) { if(is_teamplay()) { prog = max(prog, (teamscore[0]*100)/config.sv_scorelimit); prog = max(prog, (teamscore[1]*100)/config.sv_scorelimit); } else { for(int i = 0; i < MAX_CLIENTS; i++) { if(game.players[i]) prog = max(prog, (game.players[i]->score*100)/config.sv_scorelimit); } } } if(warmup) prog = -1; server_setbrowseinfo(gametype, prog); }
bool sp_damage( OBJ_DATA * obj, CHAR_DATA * ch, CHAR_DATA * victim, int dam, int type, int sn, bool show_msg ) { int ch_strong, ch_weak, ch_race, ch_suscept, ch_resist, vi_strong, vi_weak, vi_race, vi_suscept, vi_resist; float dam_modifier = 1.0; float tmp = 0; bool can_reflect = TRUE; bool can_absorb = TRUE; if ( victim == NULL ) return FALSE; /* * First, check caster's strengths and weaknesses. * */ if ( IS_SET( type, NO_REFLECT ) ) { REMOVE_BIT( type, NO_REFLECT ); can_reflect = FALSE; } if ( IS_SET( type, NO_ABSORB ) ) { REMOVE_BIT( type, NO_ABSORB ); can_absorb = FALSE; } if ( obj == NULL ) { if ( ( can_reflect ) && ( skill_table[sn].target == TAR_CHAR_OFFENSIVE ) && ( IS_AFFECTED( victim, AFF_CLOAK_REFLECTION ) ) && ( ch != victim ) && ( number_percent( ) < ( victim->get_level("psuedo") - 70 ) ) ) { act( "@@N$n's @@lc@@el@@ro@@ya@@ak@@N glows brightly as $Nn's spell hits it, and the spell is reflected@@N!!", ch, victim, NULL, TO_ROOM ); act( "@@N$N's @@lc@@el@@ro@@ya@@ak@@N glows brightly, and reflects your spell back on you@@N!!", ch, NULL, victim, TO_CHAR ); act( "@@NYour @@lc@@el@@ro@@ya@@ak@@N glows brightly, and reflects the spell back on $N@@N!!!", victim, NULL, ch, TO_CHAR ); ( *skill_table[sn].spell_fun ) ( sn, 60, ch, ( void * )ch, NULL ); return FALSE; } else if ( ( can_reflect ) && ( skill_table[sn].target == TAR_CHAR_OFFENSIVE ) && ( IS_AFFECTED( victim, AFF_CLOAK_ABSORPTION ) ) && ( ch != victim ) && ( number_percent( ) < ( victim->get_level("psuedo") - 55 ) ) ) { int mana; mana = mana_cost( ch, sn ); victim->mana = UMIN( victim->max_mana, victim->mana + mana ); act( "@@N$n's @@lcloak@@N glows brightly as $N's spell hits it, then fades@@N!!", victim, NULL, ch, TO_ROOM ); act( "@@N$N's @@lcloak@@N glows brightly, and absorbs your spell@@N!!", ch, NULL, victim, TO_CHAR ); act( "@@NYour @@lcloak@@N glows brightly, and absorbs $N's spell@@N!!!", victim, NULL, ch, TO_CHAR ); return FALSE; } ch_strong = ( IS_NPC( ch ) ? ( ( ( ch->race > 0 ) && ( ch->race < MAX_RACE ) ) ? race_table[ch->race].strong_realms : ch->npcdata->strong_magic ) : race_table[ch->race].strong_realms ); ch_resist = ( IS_NPC( ch ) ? ( ( ( ch->race > 0 ) && ( ch->race < MAX_RACE ) ) ? race_table[ch->race].resist_realms : ch->npcdata->resist ) : race_table[ch->race].resist_realms ); ch_weak = ( IS_NPC( ch ) ? ( ( ( ch->race > 0 ) && ( ch->race < MAX_RACE ) ) ? race_table[ch->race].weak_realms : ch->npcdata->weak_magic ) : race_table[ch->race].weak_realms ); ch_suscept = ( IS_NPC( ch ) ? ( ( ( ch->race > 0 ) && ( ch->race < MAX_RACE ) ) ? race_table[ch->race].suscept_realms : ch->npcdata->suscept ) : race_table[ch->race].suscept_realms ); ch_race = ( IS_NPC( ch ) ? ( ( ( ch->race > 0 ) && ( ch->race < MAX_RACE ) ) ? race_table[ch->race].race_flags : ch->race_mods ) : race_table[ch->race].race_flags ); if ( IS_SET( ch_strong, type ) ) { dam_modifier += .35; } else if ( IS_SET( ch_weak, type ) ) { dam_modifier -= .35; } if ( IS_SET( ch_race, RACE_MOD_STRONG_MAGIC ) ) { dam_modifier += .25; } else if ( IS_SET( ch_race, RACE_MOD_WEAK_MAGIC ) ) { dam_modifier -= .25; } else if ( IS_SET( ch_race, RACE_MOD_NO_MAGIC ) ) { dam_modifier -= .50; } if ( ch->stance == STANCE_CASTER ) dam_modifier += .10; else if ( ch->stance == STANCE_WIZARD ) dam_modifier += .25; else if ( ch->stance == STANCE_MAGI ) dam_modifier += .30; if ( ( !IS_NPC( ch ) ) && ( !IS_SET( type, REALM_MIND ) ) ) { if ( ch->pcdata->learned[gsn_potency] > 0 ) { dam_modifier += ( get_curr_int( ch ) * ch->pcdata->learned[gsn_potency] / 5000 ); } if ( ch->pcdata->learned[gsn_thaumatergy] > 0 ) { dam_modifier += ( get_curr_int( ch ) * ch->pcdata->learned[gsn_thaumatergy] / 2500 ); } } if ( is_affected( ch, skill_lookup( "mystical focus" ) ) ) { dam_modifier += .5; } } /* obj == NULL */ else if ( obj->carried_by != NULL ) { ch = obj->carried_by; } else { snprintf( log_buf, (2 * MIL), "Error, object %s casting spell, but not carried by anyone.", obj->short_descr ); monitor_chan( log_buf, MONITOR_DEBUG ); return FALSE; } /* * Next, the victim * */ vi_strong = ( IS_NPC( victim ) ? ( ( ( victim->race > 0 ) && ( victim->race < MAX_RACE ) ) ? race_table[victim->race].strong_realms : victim->npcdata->strong_magic ) : race_table[victim->race].strong_realms ); vi_resist = ( IS_NPC( victim ) ? ( ( ( victim->race > 0 ) && ( victim->race < MAX_RACE ) ) ? race_table[victim->race].resist_realms : victim->npcdata->resist ) : race_table[victim->race].resist_realms ); vi_weak = ( IS_NPC( victim ) ? ( ( ( victim->race > 0 ) && ( victim->race < MAX_RACE ) ) ? race_table[victim->race].weak_realms : victim->npcdata->weak_magic ) : race_table[victim->race].weak_realms ); vi_suscept = ( IS_NPC( victim ) ? ( ( ( victim->race > 0 ) && ( victim->race < MAX_RACE ) ) ? race_table[victim->race].suscept_realms : victim->npcdata->suscept ) : race_table[victim->race].suscept_realms ); vi_race = ( IS_NPC( victim ) ? ( ( ( victim->race > 0 ) && ( victim->race < MAX_RACE ) ) ? race_table[victim->race].race_flags : victim->race_mods ) : race_table[victim->race].race_flags ); if ( IS_SET( vi_suscept, type ) ) { dam_modifier += .45; } else if ( IS_SET( vi_resist, type ) ) { dam_modifier -= .45; } else if ( IS_SET( vi_race, RACE_MOD_NO_MAGIC ) ) { dam_modifier -= .25; } if ( MAGIC_STANCE( ch ) ) dam_modifier += .15; if ( ( IS_SET( type, REALM_MIND ) ) && ( !HAS_MIND( victim ) ) ) dam_modifier = 0.0; else if ( ( ( IS_SET( type, REALM_IMPACT ) ) || ( IS_SET( type, REALM_ACID ) ) || ( IS_SET( type, REALM_GAS ) ) ) && ( !HAS_BODY( victim ) ) ) dam_modifier = 0.0; if ( ( IS_SET( type, REALM_POISON ) ) && ( IS_SET( vi_race, RACE_MOD_IMMUNE_POISON ) ) ) dam_modifier = 0.0; if ( ( IS_SET( type, REALM_DRAIN ) ) && ( IS_UNDEAD( victim ) ) ) dam_modifier = 0.0; tmp = dam; tmp *= dam_modifier; if ( check_charm_aff(ch, CHARM_AFF_MAGE) ) tmp *= ((100 + get_charm_bonus(ch, CHARM_AFF_MAGE)) / 100); dam = static_cast<int>(tmp); dam += number_range(static_cast<int>((dam * -0.10)), static_cast<int>((dam * 0.10))); /* Lets add a little randomness to things. --Kline */ if ( victim != ch ) { /* * Certain attacks are forbidden. * Most other attacks are returned. */ if ( is_safe( ch, victim ) ) return FALSE; if ( victim != ch->fighting ) check_killer( ch, victim ); if ( victim->position > POS_STUNNED ) { if ( victim->fighting == NULL ) set_fighting( victim, ch, FALSE ); victim->position = POS_FIGHTING; } if ( victim->position > POS_STUNNED ) { if ( ch->fighting == NULL ) { set_fighting( ch, victim, TRUE ); } /* * If victim is charmed, ch might attack victim's master. */ if ( IS_NPC( ch ) && IS_NPC( victim ) && IS_AFFECTED( victim, AFF_CHARM ) && victim->master != NULL && victim->master->in_room == ch->in_room && number_bits( 3 ) == 0 ) { stop_fighting( ch ); one_hit( ch, victim->master, TYPE_UNDEFINED ); } } /* * More charm stuff. */ if ( victim->master == ch ) stop_follower( victim ); /* * Inviso attacks ... not. */ if ( IS_AFFECTED( ch, AFF_INVISIBLE ) ) { affect_strip( ch, gsn_invis ); affect_strip( ch, gsn_mass_invis ); REMOVE_BIT( ch->affected_by, AFF_INVISIBLE ); act( "$n shimmers into existence.", ch, NULL, NULL, TO_ROOM ); } /* * Damage modifiers. */ if ( dam < 0 ) dam = 0; /* * Stop up any residual loopholes. */ if ( dam > sysdata.damcap ) { char buf[MAX_STRING_LENGTH]; snprintf( buf, MSL, "Spell: %d damage by %s, spell %s", dam, ( obj == NULL ) ? ch->get_name() : obj->short_descr, skill_table[sn].name ); if ( ch->level < 82 ) monitor_chan( buf, MONITOR_MAGIC ); log_f( "%s", buf ); dam = sysdata.damcap; } if ( ( show_msg ) && ( dam >= 0 ) ) sp_dam_message( obj, ch, victim, dam, type, sn ); } /* * Hurt the victim. * Inform the victim of his new state. */ victim->hit -= dam; if ( !IS_NPC(ch) ) { if ( dam > ch->pcdata->records->mdam_amt ) { send_to_char("@@yYou've broken your magical damage record!@@N\r\n", ch); ch->pcdata->records->mdam_amt = dam; ch->pcdata->records->mdam_gsn = sn; } } if ( !IS_NPC( victim ) ) check_adrenaline( victim, dam ); if ( !IS_NPC( victim ) && IS_WOLF( victim ) && ( dam > 350 ) ) do_rage( victim, "FORCE" ); update_pos( victim ); if ( ( IS_NPC( victim ) || !IS_VAMP( victim ) ) && !( deathmatch ) ) { switch ( victim->position ) { case POS_MORTAL: act( "$n is mortally wounded, and will die soon, if not aided.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are mortally wounded, and will die soon, if not aided.\r\n", victim ); break; case POS_INCAP: act( "$n is incapacitated and will slowly die, if not aided.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are incapacitated and will slowly die, if not aided.\r\n", victim ); break; case POS_STUNNED: act( "$n is too stunned to do anything!", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are too stunned to do anything!\r\n", victim ); break; case POS_DEAD: act( "$n is DEAD!!", victim, 0, 0, TO_ROOM ); send_to_char( "You have been KILLED!!\r\n\r\n", victim ); break; default: if ( dam > victim->max_hit / 4 ) send_to_char( "That really did HURT!\r\n", victim ); if ( victim->hit < victim->max_hit / 4 ) send_to_char( "You sure are BLEEDING!\r\n", victim ); break; } } /* end of if statement */ /* * Sleep spells and extremely wounded folks. */ if ( !IS_AWAKE( victim ) ) stop_fighting( victim ); /* * Payoff for killing things. */ if ( victim->position == POS_DEAD && ( IS_NPC( victim ) || !IS_VAMP( victim ) || ( deathmatch ) ) ) { group_gain( ch, victim ); /* * Sort out kill counts..... */ if ( !IS_NPC( ch ) ) { if ( !IS_NPC( victim ) ) ch->pcdata->records->pk++; else ch->pcdata->records->mk++; } if ( !IS_NPC( victim ) ) { if ( !IS_NPC( ch ) ) victim->pcdata->records->pd++; else victim->pcdata->records->md++; } if ( !IS_NPC( victim ) || victim->act.test(ACT_INTELLIGENT) ) { snprintf( log_buf, (2 * MIL), "%s killed by %s at %d", victim->get_name(), ch->get_name(), victim->in_room->vnum ); log_string( log_buf ); notify( log_buf, 82 ); /* * As level gain is no longer automatic, a dead char loses * * 1/2 their gained exp. -S- * * Fixed my bug here too, hehe! */ if ( victim->exp > 0 ) { int lose = (victim->exp / 2); lose *= -1; victim->gain_exp(lose); } } if ( IS_NPC( ch ) ) raw_kill( victim, "" ); else { char name_buf[MAX_STRING_LENGTH]; snprintf( name_buf, MSL, "%s", ch->name.c_str() ); raw_kill( victim, name_buf ); } if ( deathmatch && !IS_NPC( victim ) ) do_quit( victim, "" ); if ( IS_NPC( ch ) && IS_NPC( victim ) && ch->act.test(ACT_INTELLIGENT) ) { do_get( ch, "all corpse" ); do_sacrifice( ch, "corpse" ); } if ( !IS_NPC( ch ) && IS_NPC( victim ) ) { if ( ch->act.test(ACT_AUTOLOOT) ) do_get( ch, "all corpse" ); else do_look( ch, "in corpse" ); if ( ch->act.test(ACT_AUTOSAC) ) do_sacrifice( ch, "corpse" ); } return FALSE; } if ( victim == ch ) return TRUE; /* * Take care of link dead people. */ if ( !IS_NPC( victim ) && victim->desc == NULL ) { if ( number_range( 0, victim->wait ) == 0 ) { do_recall( victim, "" ); return TRUE; } } /* * Wimp out? */ if ( IS_NPC( victim ) && dam > 0 ) { if ( ( victim->act.test(ACT_WIMPY) && number_bits( 1 ) == 0 && victim->hit < victim->max_hit / 2 ) || ( IS_AFFECTED( victim, AFF_CHARM ) && victim->master != NULL && victim->master->in_room != victim->in_room ) ) do_flee( victim, "" ); } if ( !IS_NPC( victim ) && victim->hit > 0 && victim->hit <= victim->wimpy && victim->wait == 0 ) do_flee( victim, "" ); return TRUE; }
void do_mount_on( CHAR_DATA *ch, CHAR_DATA *horse ) { bool show; int skill = get_skill( ch, gsn_riding ); if ( ch->mount ) { print_char(ch, "Przecie¿ dosiadasz ju¿ %s!\n\r", ch->mount->name4); return; } if ( horse == ch ) { send_to_char( "Czego chcesz dosi±¶æ?\n\r", ch ); return; } if ( !IS_NPC(horse) || !EXT_IS_SET(horse->act, ACT_MOUNTABLE ) ) { print_char(ch, "Nie mo¿esz dosi±¶æ %s!\n\r", horse->name2 ); return; } if ( horse->mounting ) { print_char(ch, "%s ju¿ ma je¼dzca.\n\r", horse->short_descr ); return; } if ( horse->master && horse->master != ch ) { act("$N nie pozwala ci na to.", ch, NULL, horse->master, TO_CHAR ); return; } if ( horse->position < POS_STANDING ) { send_to_char( "Wierzchowiec musi staæ, aby mo¿na by³o na niego wsi±¶æ.\n\r", ch ); return; } if ( horse->fighting ) { print_char(ch, "%s teraz walczy, nie dasz rady wsi±¶æ.\n\r", horse->short_descr ); return; } if ( is_fearing( horse, ch ) ) { print_char(ch, "%s zbyt siê ciebie boi, nie dasz rady wsi±¶æ.\n\r", horse->short_descr ); if ( number_percent() < 5 ) { one_hit( horse, ch, TYPE_UNDEFINED, FALSE ); } return; } if ( ch->move <= 0 ) { act( "Jeste¶ zbyt zmêczon<&y/a/e> by dosi±¶æ wierzchowca.", ch, NULL, horse, TO_CHAR ); return; } if (IS_AFFECTED(ch, AFF_SNEAK) || IS_AFFECTED(ch, AFF_HIDE)) { switch (horse->sex) { case SEX_NEUTRAL: act( "Próbujesz dosi±¶æ $C, ale robisz to tak niespodziewanie, ¿e $N umyka przestraszone.", ch, NULL, horse, TO_CHAR ); break; case SEX_MALE: act( "Próbujesz dosi±¶æ $C, ale robisz to tak niespodziewanie, ¿e $N umyka przestraszony.", ch, NULL, horse, TO_CHAR ); break; case SEX_FEMALE: default : act( "Próbujesz dosi±¶æ $C, ale robisz to tak niespodziewanie, ¿e $N umyka przestraszona.", ch, NULL, horse, TO_CHAR ); break; } ch->move -= number_range(1,4); if ( ch->move < 0 ) { ch->move = 0; } return; } if(IS_AFFECTED(ch, AFF_FLYING)) { affect_strip(ch, gsn_fly); } if(IS_AFFECTED(ch, AFF_FLOAT)) { affect_strip(ch, gsn_float); } if ( skill == 0 || number_percent() > skill + 5 ) { act( "Nieudolnie próbujesz dosi±¶æ $C i po chwili l±dujesz na ziemi.", ch, NULL, horse, TO_CHAR ); act( "$n nieudolnie próbuje dosi±¶æ $C i po chwili l±duje na ziemi.", ch, NULL, horse, TO_NOTVICT ); ch->position = POS_SITTING; ch->move -= number_range(0,4); if ( ch->weight > 900 ) { ch->move -= number_range(0,2); } ch->move = UMAX(0,ch->move); check_improve( ch, NULL, gsn_riding, TRUE, 70 ); return; } ch->mount = horse; horse->mounting = ch; horse->default_pos = POS_STANDING; horse->position = POS_STANDING; show = TRUE; if ( IS_NPC( horse ) && HAS_TRIGGER( horse, TRIG_MOUNT ) ) { show = !mp_percent_trigger( horse, ch, NULL, NULL, &TRIG_MOUNT ); } if ( IS_NPC( horse ) && HAS_TRIGGER( horse, TRIG_DISMOUNT ) ) { show = FALSE; } if ( show ) { act( "Umiejêtnie dosiadasz $C.", ch, NULL, horse, TO_CHAR ); act( "$n umiejêtnie dosiada $C.", ch, NULL, horse, TO_NOTVICT ); check_improve( ch, NULL, gsn_riding, TRUE, 10 ); } return; }
/* procedure for all mobile attacks */ void mob_hit (CHAR_DATA *ch, CHAR_DATA *victim, int dt) { int number; CHAR_DATA *vch, *vch_next; one_hit(ch,victim,dt); if (ch->fighting != victim) return; /* Area attack -- BALLS nasty! */ if (IS_SET(ch->off_flags,OFF_AREA_ATTACK)) { for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next; if ((vch != victim && vch->fighting == ch)) one_hit(ch,vch,dt); } } if (ch->fighting != victim || dt == gsn_backstab) return; /* oh boy! Fun stuff! */ if (ch->wait > 0) return; /* now for the skills */ number = number_range(0,8); switch(number) { case (0) : if (IS_SET(ch->off_flags,OFF_BASH)) do_function(ch, &do_bash,""); break; case (1) : break; case (2) : if (IS_SET(ch->off_flags,OFF_DISARM) || (get_weapon_sn(ch) != gsn_brawl )) do_function(ch, &do_disarm,""); break; case (3) : if (IS_SET(ch->off_flags,OFF_KICK)) do_function(ch, &do_kick,""); break; case (4) : if (IS_SET(ch->off_flags,OFF_KICK_DIRT)) do_function(ch, &do_dirt,""); break; case (5) : if (IS_SET(ch->off_flags,OFF_TAIL)) { /* do_tail(ch,"") */ ; } break; case (6) : if (IS_SET(ch->off_flags,OFF_TRIP)) do_function(ch, &do_trip,""); break; case (7) : if (IS_SET(ch->off_flags,OFF_CRUSH)) { /* do_crush(ch,"") */ ; } break; case (8) : if (IS_SET(ch->off_flags,OFF_BACKSTAB)) { do_function(ch, &do_backstab,""); } } }
void check_samuraiattack(CHAR_DATA *ch, CHAR_DATA *victim) { if (!IS_CLASS(ch, CLASS_SAMURAI)) return; if (!victim || victim->hit < 1000) return; switch(ch->pcdata->powers[SAMURAI_FOCUS]) { default : break; case 10 : if (ch->pcdata->powers[SAMURAI_LAST] == 10) { send_to_char("You cannot use the same combo twice.\n\r",ch); break; } ch->pcdata->powers[SAMURAI_LAST] = 10; do_say(ch, "What a worthless opponent you are. Here, let me show you how a real fighter fights."); one_hit(ch, victim, gsn_lightningslash, 1); one_hit(ch, victim, gsn_lightningslash, 1); one_hit(ch, victim, gsn_lightningslash, 1); break; case 15 : if (ch->pcdata->powers[SAMURAI_LAST] == 15) { send_to_char("You cannot use the same combo twice.\n\r",ch); break; } ch->pcdata->powers[SAMURAI_LAST] = 15; if (number_range(1,3) == 2) { send_to_char("You fail your attempt to disarm.\n\r",ch); break; } act("#GYou strike out at $N's weapon.#n",ch,NULL,victim,TO_CHAR); act("#G$n's attack strikes your weaponarm.#n",ch,NULL,victim,TO_VICT); disarm(ch, victim); break; case 20 : if (ch->pcdata->powers[SAMURAI_LAST] == 20) { send_to_char("You cannot use the same combo twice.\n\r",ch); break; } ch->pcdata->powers[SAMURAI_LAST] = 20; act("#GYour hit $N on a central nerve, paralysing $M.#n",ch,NULL,victim,TO_CHAR); act("#G$n's attack paralyses you, you cannot move.#n",ch,NULL,victim,TO_VICT); if (IS_CLASS(victim, CLASS_FAE)) { send_to_char("You shrug of the attack.\n\r", victim); send_to_char("They don't seem that affected.\n\r", ch); } else WAIT_STATE(victim, 24); break; case 25 : if (ch->pcdata->powers[SAMURAI_LAST] == 25) { send_to_char("You cannot use the same combo twice.\n\r",ch); break; } ch->pcdata->powers[SAMURAI_LAST] = 25; if (number_range(1,3) == 2) { send_to_char("You fail your attempt to hurl.\n\r",ch); break; } act("#GYou grab $N and toss $M over your shoulder.#n",ch,NULL,victim,TO_CHAR); act("#G$n grabs you, and tosses you over $s shoulder.#n",ch,NULL,victim,TO_VICT); special_hurl(ch, victim); break; case 30 : if (ch->pcdata->powers[SAMURAI_LAST] == 30) { send_to_char("You cannot use the same combo twice.\n\r",ch); break; } ch->pcdata->powers[SAMURAI_LAST] = 30; ch->hit += number_range(2000, 4000); if (ch->hit > ch->max_hit) ch->hit = ch->max_hit; act("#GYou feel adrenalin pump through your body, awakening your senses.#n",ch,NULL,victim,TO_CHAR); act("#G$n flashes a wicked smile.#n",ch,NULL,victim,TO_VICT); break; case 35 : if (ch->pcdata->powers[SAMURAI_LAST] == 35) { send_to_char("You cannot use the same combo twice.\n\r",ch); break; } ch->pcdata->powers[SAMURAI_LAST] = 35; do_say(ch, "I am a master of arms, you cannot even begin to understand what I am able to do!"); one_hit(ch, victim, gsn_backfist, 1); one_hit(ch, victim, gsn_thrustkick, 1); one_hit(ch, victim, gsn_monksweep, 1); one_hit(ch, victim, gsn_jumpkick, 1); one_hit(ch, victim, gsn_lightningslash, 1); break; } return; }
/* i have condensed this function to just three states: MOB_FIGHTING, * MOB_RESTING/ MOB_SLEEPING, and MOB_STANDING. each of these three states * will call it's appropriate function. */ void int_group_handler( NPC_GROUP_DATA * ngroup ) { CHAR_DATA *follower = NULL; CHAR_DATA *leader = ngroup->leader; DL_LIST *follower_ptr; // short followers_want = GRP_STATE_NO_CHANGE; short leader_wants = GRP_STATE_NO_CHANGE; short group_count = 1; // start with leader char monbuf[MSL]; if ( leader == NULL ) { monitor_chan( "No Leader in NPC_GROUP", MONITOR_MOB ); return; } // check for followers needs for ( follower_ptr = ngroup->first_follower; follower_ptr; follower_ptr = follower_ptr->next ) { // check for needing healing, levelling follower = (CHAR_DATA *)follower_ptr->this_one; group_count++; continue; } // check for leader's needs if ( leader->hit < leader->max_hit * 25 / 100 ) { leader_wants = GRP_STATE_CRIT_HEAL; } else if ( leader->mana < leader->max_mana * 25 / 100 ) { leader_wants = GRP_STATE_CRIT_MANA; } else if ( leader->hit < leader->max_hit * 60 / 100 ) { leader_wants = GRP_STATE_NORM_HEAL; } else if ( leader->mana < leader->max_mana * 50 / 100 ) { leader_wants = GRP_STATE_NORM_MANA; } else if ( able_to_level( leader ) ) { leader_wants = GRP_STATE_LEVELING; } snprintf( monbuf, MSL, "NPC Group Handler, Leader is %s, state is %s", ngroup->leader->name.c_str(), group_state_table[ngroup->state] ); monitor_chan( monbuf, MONITOR_MOB ); switch ( ngroup->state ) { case GRP_STATE_CRIT_HEAL: case GRP_STATE_CRIT_MANA: case GRP_STATE_NORM_HEAL: case GRP_STATE_NORM_MANA: { bool everyone_ready = TRUE; bool room_ready = FALSE; // ready_heal_room( leader ); if ( ( leader->mana < leader->max_mana * 85 / 100 ) || ( leader->hit < leader->max_hit * 85 / 100 ) ) { everyone_ready = FALSE; if ( ( ( room_ready = ready_heal_room( leader ) ) == TRUE ) || ( leader->mana < leader->max_mana * 20 / 100 ) ) { do_sleep( leader, "" ); } } else { do_stand( leader, "" ); } for ( follower_ptr = ngroup->first_follower; follower_ptr; follower_ptr = follower_ptr->next ) { follower = (CHAR_DATA *)follower_ptr->this_one; if ( ( follower->mana < follower->max_mana * 75 / 100 ) || ( follower->hit < follower->max_hit * 75 / 100 ) ) { everyone_ready = FALSE; do_sleep( follower, "" ); } else { do_stand( follower, "" ); } } if ( everyone_ready == TRUE ) { ngroup->state = GRP_STATE_IDLE; } break; } case GRP_STATE_FIGHT: { // violence_update will handle if ( ( leader_wants < GRP_STATE_HUNTING ) || ( leader->fighting == NULL ) ) { bool someone_still_fighting = FALSE; ngroup->state = GRP_STATE_FLEE; for ( follower_ptr = ngroup->first_follower; follower_ptr; follower_ptr = follower_ptr->next ) { follower = (CHAR_DATA *)follower_ptr->this_one; if ( follower->fighting != NULL ) { do_flee( follower, "" ); someone_still_fighting = TRUE; } } if ( someone_still_fighting == FALSE ) { ngroup->state = GRP_STATE_REFORM; } if ( leader->fighting != NULL ) { do_flee( leader, "" ); } } break; } case GRP_STATE_FLEE: { bool someone_still_fighting = FALSE; for ( follower_ptr = ngroup->first_follower; follower_ptr; follower_ptr = follower_ptr->next ) { follower = (CHAR_DATA *)follower_ptr->this_one; if ( follower->fighting != NULL ) { do_flee( follower, "" ); someone_still_fighting = TRUE; } } if ( leader->fighting != NULL ) { do_flee( leader, "" ); someone_still_fighting = TRUE; } if ( someone_still_fighting == FALSE ) { ngroup->state = GRP_STATE_REFORM; } break; } case GRP_STATE_IDLE: { // check_re_equip( leader ); // check_rewield( leader ); if ( leader_wants < GRP_STATE_NO_CHANGE ) { ngroup->state = leader_wants; break; } else if ( number_percent( ) < 40 ) { select_target( ngroup->leader ); ngroup->state = GRP_STATE_HUNTING; break; } } case GRP_STATE_HUNTING: { // poll followers later short move_dir; if ( leader->fighting != NULL ) { ngroup->state = GRP_STATE_FIGHT; break; } if ( leader->hunting == NULL ) { // snprintf( monbuf, MSL, "Leader %s not hunting anything in GRP_STATE_HUNTING", // leader->name ); // monitor_chan( monbuf, MONITOR_MOB ); select_target( ngroup->leader ); break; } if ( leader->in_room == leader->hunting->in_room ) { ngroup->state = GRP_STATE_FIGHT; one_hit( leader, leader->hunting, TYPE_UNDEFINED ); break; } move_dir = h_find_dir( leader->in_room, leader->hunting->in_room, HUNT_WORLD | HUNT_OPENDOOR | HUNT_UNLOCKDOOR | HUNT_PICKDOOR ); if ( move_dir < 0 ) // can't get there from here { ngroup->state = GRP_STATE_LOST; break; } hunt_move( leader, move_dir ); break; } case GRP_STATE_LEVELING: { char_from_room( leader ); char_to_room( leader, get_room_index( 3758 ) ); if ( able_to_level( leader ) ) { gain_level( leader ); } for ( follower_ptr = ngroup->first_follower; follower_ptr; follower_ptr = follower_ptr->next ) { follower = (CHAR_DATA *)follower_ptr->this_one; if ( able_to_level( follower ) ) { gain_level( follower ); } } ngroup->state = GRP_STATE_IDLE; break; } case GRP_STATE_REFORM: { bool all_are_here = TRUE; for ( follower_ptr = ngroup->first_follower; follower_ptr; follower_ptr = follower_ptr->next ) { follower = (CHAR_DATA *)follower_ptr->this_one; if ( follower->in_room != leader->in_room ) { short move_dir; all_are_here = FALSE; move_dir = h_find_dir( follower->in_room, leader->in_room, HUNT_WORLD | HUNT_OPENDOOR | HUNT_UNLOCKDOOR | HUNT_PICKDOOR ); if ( move_dir < 0 ) // can't get there from here { ngroup->state = GRP_STATE_LOST; break; } hunt_move( follower, move_dir ); } } if ( all_are_here == TRUE ) { ngroup->state = GRP_STATE_IDLE; } break; } } }