void die_follower( CHAR_DATA * ch, char * name ) { CHAR_DATA * fch; if ( ch->master ) { stop_follower( ch ); } ch->leader = NULL; for ( fch = char_list; fch; fch = fch->next ) { if ( fch->deleted ) { continue; } if ( fch->master == ch ) { stop_follower( fch ); } if ( fch->leader == ch ) { fch->leader = NULL; } } return; }
void wolf_hunger() { struct char_data *ch; struct char_data *next_ch; // Let's Use GET_MOB_HUNGER for hunger as a cop out. for (ch = character_list; ch; ch = next_ch) { next_ch = ch->next; if (!GET_MOB_HUNGER(ch)) { continue; } GET_MOB_HUNGER(ch)--; if (!GET_MOB_HUNGER(ch)) { continue; } GET_MOB_HUNGER(ch)--; // if a wolf gets really hungry and is following a player, it should stop following if (IS_NPC_WOLF(ch) && GET_MOB_HUNGER(ch) < 6 && ch->master) { stop_follower(ch); } } }
void do_follow( CHAR_DATA * ch, char * argument ) { CHAR_DATA * victim; char arg[ MAX_INPUT_LENGTH ]; one_argument( argument, arg ); if ( arg[ 0 ] == '\0' ) { send_to_char( AT_DGREEN, "Follow whom?\n\r", ch ); return; } if ( !( victim = get_char_room( ch, arg ) ) ) { send_to_char( AT_DGREEN, "They aren't here.\n\r", ch ); return; } if ( IS_AFFECTED( ch, AFF_CHARM ) && ch->master ) { act( AT_DGREEN, "But you'd rather follow $N!", ch, NULL, ch->master, TO_CHAR ); return; } if ( victim == ch ) { if ( !ch->master ) { send_to_char( AT_DGREEN, "Silly...you already follow yourself.\n\r", ch ); return; } stop_follower( ch ); return; } if ( ( ch->level - victim->level < -8 || ch->level - victim->level > 8 ) && !IS_HERO( ch ) ) { send_to_char( AT_DGREEN, "You feel unworthy to follow.\n\r", ch ); return; } if ( ch->master ) { stop_follower( ch ); } add_follower( ch, victim ); return; }
void die_follower( CHAR_DATA *ch ) { CHAR_DATA *fch; if ( ch->master != NULL ) stop_follower( ch ); ch->leader = NULL; for ( fch = char_list; fch != NULL; fch = fch->next ) { if ( fch->master == ch ) stop_follower( fch ); if ( fch->leader == ch ) fch->leader = fch; } return; }
void do_follow( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; CHAR_DATA *victim; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Follow whom?\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master != NULL ) { act( "You don't wish to leave your beloved master!", ch, ch->master, NULL, NULL, NULL, TO_CHAR, SENSE_SIXTH ); return; } if ( victim == ch ) { if ( ch->master == NULL ) { send_to_char( "You already follow yourself.\n\r", ch ); return; } stop_follower( ch ); return; } if ( ch->master != NULL ) stop_follower( ch ); add_follower( ch, victim ); return; }
void react_attack( char_data* ch, char_data* victim ) { char_data* rch; if( victim->leader == ch ) stop_follower( victim ); if( ch->leader == victim ) stop_follower( ch ); init_attack( victim, ch ); for( int i = 0; i < *ch->array; i++ ) { if( ( rch = character( ch->array->list[i] ) ) != NULL ) { if( join_fight( victim, ch, rch ) ) init_attack( rch, ch ); else if( join_fight( ch, victim, rch ) ) init_attack( rch, victim ); } } }
bool spell_tame( char_data* ch, char_data* victim, void*, int level, int ) { if( null_caster( ch, SPELL_TAME ) ) return TRUE; if( is_set( &victim->status, STAT_PET ) ) { send( ch, "%s is already tame.\r\n", victim ); return TRUE; } if( victim->species == NULL || !is_set( &victim->species->act_flags, ACT_CAN_TAME ) || makes_save( victim, ch, RES_MIND, SPELL_TAME, level ) || victim->leader != NULL || victim->shdata->level > ch->shdata->level ) { send( ch, "%s ignores you.\r\n", victim ); send( *ch->array, "%s ignores %s.\r\n", victim, ch ); return TRUE; } if( victim->shdata->level > ch->shdata->level-pet_levels( ch ) ) { send( ch, "You fail as you are unable to control more animals.\r\n" ); return TRUE; } if( is_set( &victim->species->act_flags, ACT_MOUNT ) && has_mount( ch ) ) return TRUE; if( ch->leader == victim ) stop_follower( ch ); set_bit( &victim->status, STAT_PET ); set_bit( &victim->status, STAT_TAMED ); remove_bit( &victim->status, STAT_AGGR_ALL ); remove_bit( &victim->status, STAT_AGGR_GOOD ); remove_bit( &victim->status, STAT_AGGR_EVIL ); add_follower( victim, ch ); return TRUE; }
/* * Alert: As of bpl14, this function returns the following codes: * < 0 Victim died. * = 0 No damage. * > 0 How much damage done. */ int damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype) { if (GET_POS(victim) <= POS_DEAD) { /* This is "normal"-ish now with delayed extraction. -gg 3/15/2001 */ if (PLR_FLAGGED(victim, PLR_NOTDEADYET) || MOB_FLAGGED(victim, MOB_NOTDEADYET)) return (-1); log("SYSERR: Attempt to damage corpse '%s' in room #%d by '%s'.", GET_NAME(victim), GET_ROOM_VNUM(IN_ROOM(victim)), GET_NAME(ch)); die(victim); return (-1); /* -je, 7/7/92 */ } /* peaceful rooms */ if (ch != victim && ROOM_FLAGGED(IN_ROOM(ch), ROOM_PEACEFUL)) { send_to_char(ch, "This room just has such a peaceful, easy feeling...\r\n"); return (0); } /* shopkeeper protection */ if (!ok_damage_shopkeeper(ch, victim)) return (0); /* You can't damage an immortal! */ if (!IS_NPC(victim) && (GET_LEVEL(victim) >= LVL_IMMORT)) dam = 0; if (victim != ch) { /* Start the attacker fighting the victim */ if (GET_POS(ch) > POS_STUNNED && (FIGHTING(ch) == NULL)) set_fighting(ch, victim); /* Start the victim fighting the attacker */ if (GET_POS(victim) > POS_STUNNED && (FIGHTING(victim) == NULL)) { set_fighting(victim, ch); if (MOB_FLAGGED(victim, MOB_MEMORY) && !IS_NPC(ch)) remember(victim, ch); } } /* If you attack a pet, it hates your guts */ if (victim->master == ch) stop_follower(victim); /* If the attacker is invisible, he becomes visible */ if (AFF_FLAGGED(ch, AFF_INVISIBLE | AFF_HIDE)) appear(ch); /* Cut damage in half if victim has sanct, to a minimum 1 */ if (AFF_FLAGGED(victim, AFF_SANCTUARY) && dam >= 2) dam /= 2; /* Check for PK if this is not a PK MUD */ if (!pk_allowed) { check_killer(ch, victim); if (PLR_FLAGGED(ch, PLR_KILLER) && (ch != victim)) dam = 0; } /* Set the maximum damage per round and subtract the hit points */ dam = MAX(MIN(dam, 100), 0); GET_HIT(victim) -= dam; /* Gain exp for the hit */ if (ch != victim) gain_exp(ch, GET_LEVEL(victim) * dam); update_pos(victim); /* * skill_message sends a message from the messages file in lib/misc. * dam_message just sends a generic "You hit $n extremely hard.". * skill_message is preferable to dam_message because it is more * descriptive. * * If we are _not_ attacking with a weapon (i.e. a spell), always use * skill_message. If we are attacking with a weapon: If this is a miss or a * death blow, send a skill_message if one exists; if not, default to a * dam_message. Otherwise, always send a dam_message. */ if (!IS_WEAPON(attacktype)) skill_message(dam, ch, victim, attacktype); else { if (GET_POS(victim) == POS_DEAD || dam == 0) { if (!skill_message(dam, ch, victim, attacktype)) dam_message(dam, ch, victim, attacktype); } else { dam_message(dam, ch, victim, attacktype); } } /* Use send_to_char -- act() doesn't send message if you are DEAD. */ switch (GET_POS(victim)) { case POS_MORTALLYW: act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, CommTarget::TO_ROOM); send_to_char(victim, "You are mortally wounded, and will die soon, if not aided.\r\n"); break; case POS_INCAP: act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, CommTarget::TO_ROOM); send_to_char(victim, "You are incapacitated an will slowly die, if not aided.\r\n"); break; case POS_STUNNED: act("$n is stunned, but will probably regain consciousness again.", TRUE, victim, 0, 0, CommTarget::TO_ROOM); send_to_char(victim, "You're stunned, but will probably regain consciousness again.\r\n"); break; case POS_DEAD: act("$n is dead! R.I.P.", FALSE, victim, 0, 0, CommTarget::TO_ROOM); send_to_char(victim, "You are dead! Sorry...\r\n"); break; default: /* >= POSITION SLEEPING */ if (dam > (GET_MAX_HIT(victim) / 4)) send_to_char(victim, "That really did HURT!\r\n"); if (GET_HIT(victim) < (GET_MAX_HIT(victim) / 4)) { send_to_char(victim, "%sYou wish that your wounds would stop BLEEDING so much!%s\r\n", CCRED(victim, C_SPR), CCNRM(victim, C_SPR)); if (ch != victim && MOB_FLAGGED(victim, MOB_WIMPY)) do_flee(victim, NULL, 0, 0); } if (!IS_NPC(victim) && GET_WIMP_LEV(victim) && (victim != ch) && GET_HIT(victim) < GET_WIMP_LEV(victim) && GET_HIT(victim) > 0) { send_to_char(victim, "You wimp out, and attempt to flee!\r\n"); do_flee(victim, NULL, 0, 0); } break; } /* Help out poor linkless people who are attacked */ if (!IS_NPC(victim) && !(victim->desc) && GET_POS(victim) > POS_STUNNED) { do_flee(victim, NULL, 0, 0); if (!FIGHTING(victim)) { act("$n is rescued by divine forces.", FALSE, victim, 0, 0, CommTarget::TO_ROOM); GET_WAS_IN(victim) = IN_ROOM(victim); char_from_room(victim); char_to_room(victim, 0); } } /* stop someone from fighting if they're stunned or worse */ if (GET_POS(victim) <= POS_STUNNED && FIGHTING(victim) != NULL) stop_fighting(victim); /* Uh oh. Victim died. */ if (GET_POS(victim) == POS_DEAD) { if (ch != victim && (IS_NPC(victim) || victim->desc)) { if (AFF_FLAGGED(ch, AFF_GROUP)) group_gain(ch, victim); else solo_gain(ch, victim); } if (!IS_NPC(victim)) { mudlog(BRF, LVL_IMMORT, TRUE, "%s killed by %s at %s", GET_NAME(victim), GET_NAME(ch), world[IN_ROOM(victim)].name); if (MOB_FLAGGED(ch, MOB_MEMORY)) forget(ch, victim); } die(victim); return (-1); } return (dam); }
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; }
/* * Remove an affected_type structure from a char (called when duration * reaches zero). Pointer *af must never be NIL! Frees mem and calls * affect_location_apply */ void affect_remove(struct char_data * ch, struct affected_type * af, int output) { struct affected_type *temp; struct affected_type aff; bool accum_affect = FALSE; int k; if (ch->affected == NULL) { core_dump(); return; } switch (af->type) { case SPELL_CHARM: { struct char_data* victim = ch->master; if (output == 0) break; affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); if (ch->master) { stop_follower(ch); } if (victim) { if(IS_NPC(ch)) { SET_BIT(MOB_FLAGS(ch), MOB_AGGRESSIVE | MOB_MEMORY); } if (mag_savingthrow(victim, SAVING_SPELL)) { hit(victim, ch, TYPE_UNDEFINED); } } return; } case SPELL_LIGHT: if (output == 0) break; if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (world[ch->in_room].name != (char*) NULL) { world[ch->in_room].light -= 10; } } break; case SPELL_DARKNESS: if (output == 0) break; if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (world[ch->in_room].name != (char*) NULL) { world[ch->in_room].light += 10; } } break; case SPELL_BLACK_PLAGUE: mag_affects(30, ch, ch, SPELL_BREATH_OF_LIFE, SAVING_SPELL); break; case SPELL_CALL_ANIMAL_SPIRIT: case SPELL_ANIMAL_SUMMONING: case SPELL_ANIMAL_SUMMONING_II: case SPELL_ANIMAL_SUMMONING_III: case SPELL_CONJURE_ELEMENTAL: case SPELL_GREATER_ELEMENTAL: case SPELL_DUST_DEVIL: case SPELL_STICKS_TO_SNAKES: case SPELL_SUMMON_INSECTS: case SPELL_AERIAL_SERVANT: case SPELL_SUMMON_GUARD: if (IS_NPC(ch)) { if (GET_POS(ch) > POS_DEAD) { if (output == 1) { affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); GET_NAME(ch, chname); stop_fighting(ch); /*Fighting Bug Fix Jasrags*/ sprintf(buf, "%s disappears into thin air as the summoning ends.", chname); act(buf, FALSE, world[ch->in_room].people, 0, 0, TO_ROOM); FREE_NAME(chname); extract_char(ch); ch = NULL; return; } } } break; case SPELL_POLYMORPH: if (!PRF_FLAGGED(ch, PRF_NOTSELF)) { affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); return; } break; case SPELL_DONTUSEME: if(AFF_FLAGGED(ch, AFF_STANCE) && !AFF_FLAGGED(ch, AFF_TIRED)) { aff.type = SKILL_STANCE; aff.duration = 2; aff.location = APPLY_STR; aff.modifier = -2; aff.bitvector = AFF_TIRED; accum_affect = FALSE; affect_to_char(ch, &aff); } break; default: break; } if (output && (af->type > 0) && (af->type <= MAX_SPELLS) && af->type != SPELL_POLYMORPH && af->type != SPELL_DONTUSEME) { if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (*spell_wear_off_msg[af->type]) { send_to_char(spell_wear_off_msg[af->type], ch); send_to_char("\r\n", ch); } } } if (output && (af->type > 0) && (af->type <= MAX_SPELLS) && af->type == SPELL_POLYMORPH) { if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (PLR_FLAGGED(ch, PLR_RABBIT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_RABBIT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing, and your ears shrinking. You no longer feel like a rabbit.\r\n", ch); act("$n's body grows, $s ears shrinking. $n no longer looks like a rabbit.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BIRD)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BIRD); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing and your feathers falling away. You no longer feel like a bird.\r\n", ch); act("$n's body grows, $s feathers falling away as it expands. $n no longer looks like a bird.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_WOLF)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_WOLF); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your your fur shed and your teeth shrink. You no longer feel like a wolf.\r\n", ch); act("$n's teeth shrink, $s fur shedding. $n no longer looks like a wolf.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BEAR)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BEAR); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("Your claws shrink as does the rest of your body. You no longer feel like a bear.\r\n", ch); act("$n's claws shrink as does the rest of $s body. $n no longer looks like a bear.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_CAT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_CAT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your body growing, and your fur shedding. You no longer feel like a cat.\r\n", ch); act("$n's body slowly grows, $s fur shedding. $n no longer looks like a cat.\r\n", 0, ch, 0, 0, TO_ROOM); } for (k = 0; k < NUM_WEARS; k++) if (GET_EQ(ch, k)){ GET_OBJ_DISGUISE(GET_EQ(ch, k)) = 0; } } } affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); }
/* * Inflict damage from a hit. */ int damage(CHAR_DATA *ch,CHAR_DATA *victim,int dam,int dt,int dam_type, bool show, int agg, int combo) { /*OBJ_DATA *corpse;*/ bool immune; if ( victim->position == P_DEAD ) return P_DEAD; /* @@@@@ FIX TORPOR if ( victim->position == P_TORPOR ) return P_TORPOR; */ /* damage reduction */ if ( dam > 15) dam = (dam - 5)/2 + 5; if(IS_SET(ch->form, FORM_HORRID)) dam++; /* @@@@@ FIX BITE DAMAGE FOR SERPENTIS 3 if(is_affected(ch, skill_lookup("skin of the adder")) && dam_type == DAM_BITE) dam++; */ /* In case of -ve agg ratings */ if (agg < 0) agg = 0; /* soakage */ dam = do_soak(victim, dam, agg); if ( victim != ch ) { if ( victim->position > P_STUN ) { if ( victim->fighting == NULL ) { set_fighting( victim, ch ); if ( IS_NPC( victim ) && HAS_TRIGGER( victim, TRIG_KILL ) ) mp_percent_trigger( victim, ch, NULL, NULL, TRIG_KILL ); } if (victim->timer <= 4) victim->position = P_FIGHT; } if ( victim->position > P_STUN ) { if ( ch->fighting == NULL ) set_fighting( ch, victim ); } /* * More charm stuff. */ if ( victim->master == ch ) stop_follower( victim ); } /* * Inviso attacks ... not. */ if ( IS_AFFECTED(ch, AFF_INVISIBLE) ) { affect_strip( ch, gsn_invis ); REMOVE_BIT( ch->affected_by, AFF_INVISIBLE ); act( "$n fades into existence.", ch, NULL, NULL, TO_ROOM, 0 ); } /* * Damage modifiers. */ if ( dam > 1 && !IS_NPC(victim) && victim->condition[COND_DRUNK] > 10 ) dam = 9 * dam / 10; if ( dam > 1 && !IS_NPC(victim) && victim->condition[COND_HIGH] > 10 ) dam = 9 * dam / 10; if ( dam > 1 && ((IS_AFFECTED(victim, AFF_PROTECT_EVIL) && !IS_NATURAL(ch) )) ) dam -= dam / 4; immune = FALSE; /* * Check for parry, and dodge. if ( dt >= TYPE_HIT && ch != victim) { if ( check_parry( ch, victim ) ) return -1; if ( check_dodge( ch, victim ) ) return -1; } */ switch(check_immune(victim,dam_type)) { case(IS_IMMUNE): immune = TRUE; dam = 0; break; case(IS_RESISTANT): dam -= dam/3; break; case(IS_VULNERABLE): dam += dam/2; break; } if (show) dam_message( ch, victim, dam, dt, immune, combo ); if(dam > (victim->health + victim->agghealth -7)) { victim->position = P_MORT; stop_fighting(ch, TRUE); } else if(dam == (victim->health + victim->agghealth -7)) { victim->position = P_INCAP; stop_fighting(ch, TRUE); } if (dam == 0) return -1; else if(IS_SET(ch->off_flags, BANDAGED)) REMOVE_BIT(ch->off_flags, BANDAGED); /* * Hurt the victim. * Inform the victim of his new state. */ if( (victim->race == race_lookup("vampire")) && (dt == DAM_FIRE) ) { victim->agghealth -= dam; update_pos( victim, UMAX(1, agg) ); if(agg <= 0) agg = 1; } else if( (victim->race == race_lookup("werewolf")) && (dt == DAM_SILVER) ) { victim->agghealth -= dam; update_pos( victim, UMAX(1, agg) ); if(agg <= 0) agg = 1; } else if( (victim->race == race_lookup("faerie")) && (dt == DAM_IRON) ) { victim->health -= dam; victim->GHB += dam/3; update_pos( victim, agg ); } else if(agg) { victim->agghealth -= dam; update_pos( victim, agg ); } else { victim->health -= dam; update_pos( victim, 0 ); } switch( victim->position ) { case P_MORT: act( "$n is mortally wounded, and will die soon, if not aided.", victim, NULL, NULL, TO_ROOM, 0 ); send_to_char("You are mortally wounded, and may die soon, if not aided.\n\r", victim ); break; case P_INCAP: act( "$n is incapacitated and will slowly die, if not aided.", victim, NULL, NULL, TO_ROOM, 0 ); send_to_char("You are incapacitated and will slowly die, if not aided.\n\r", victim ); break; case P_TORPOR: act( "$n is mortally wounded, and will slowly die if not aided.", victim, NULL, NULL, TO_ROOM, 0 ); send_to_char("You enter torpor.\n\r", victim ); break; case P_STUN: act( "$n is stunned, but will probably recover.", victim, NULL, NULL, TO_ROOM, 0 ); send_to_char("You are stunned, but will probably recover.\n\r", victim ); break; case P_DEAD: act( "$n is DEAD!!", victim, 0, 0, TO_ROOM, 0 ); send_to_char( "You have been KILLED!!\n\r\n\r", victim ); break; default: if ( dam > MAX_HEALTH / 4 ) send_to_char( "That really did HURT!\n\r", victim ); if ( (victim->health + victim->agghealth - 7) < MAX_HEALTH / 4 ) send_to_char( "You sure are BLEEDING!\n\r", victim ); break; } if(dam_type == DAM_FIRE) fire_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); if(dam_type == DAM_COLD) cold_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); if(dam_type == DAM_LIGHTNING) shock_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); if(dam_type == DAM_ACID) acid_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); if(dam_type == DAM_POISON) poison_effect((void *) victim, agg+dam/2, dam, TARGET_CHAR); /* * Sleep spells and extremely wounded folks. */ if ( !IS_AWAKE(victim) ) stop_fighting( victim, FALSE ); /* * Payoff for killing things. */ if ( (victim->position == P_INCAP && IS_NPC(victim)) || victim->position == P_DEAD || victim->position == P_TORPOR ) { if ( !IS_NPC(victim) ) { log_string( LOG_GAME, Format("%s killed by %s at %d", victim->name, (IS_NPC(ch) ? ch->short_descr : ch->name), ch->in_room->vnum) ); } snprintf( log_buf, 2*MIL, "\tY[WIZNET]\tn %s got toasted by %s at %s [room %d]", (IS_NPC(victim) ? victim->short_descr : victim->name), (IS_NPC(ch) ? ch->short_descr : ch->name), ch->in_room->name, ch->in_room->vnum); if (IS_NPC(victim)) wiznet(log_buf,NULL,NULL,WIZ_MOBDEATHS,0,0); else wiznet(log_buf,NULL,NULL,WIZ_DEATHS,0,0); /* * Death trigger */ if ( IS_NPC( victim ) && HAS_TRIGGER( victim, TRIG_DEATH) ) { victim->position = P_STAND; mp_percent_trigger( victim, ch, NULL, NULL, TRIG_DEATH ); } if((!str_cmp(ch->description, "") || strlen(ch->description) < 10) && ch->played > 10*60*60) { send_to_char("No experience without a description.\n\r", ch); } else { if(ch->ooc_xp_count < 2) { send_to_char("You learn from your encounter.\n\r", ch); ch->oocxp += 1; ch->ooc_xp_count++; } else if(IS_SET(victim->act2, ACT2_HUNTER) && ch->ooc_xp_count < 50) { send_to_char("You learn from your encounter.\n\r", ch); ch->exp += 1; ch->ooc_xp_count++; } } if(ch->quest) { if(ch->quest->quest_type == Q_HITMAN && ch->quest->victim == victim) (*quest_table[ch->quest->quest_type].q_fun) (ch, 2); if(victim->quest != NULL && victim->quest->quest_type == Q_HITMAN && victim->quest->victim == victim && victim->quest->questor != ch) (*quest_table[victim->quest->quest_type].q_fun) (victim->quest->questor, 3); if(victim->quest != NULL && (victim->quest->quest_type == Q_BODYGUARD || victim->quest->quest_type == Q_RESCUE) && victim->quest->victim == victim) (*quest_table[victim->quest->quest_type].q_fun) (victim->quest->questor, 3); } if(victim->position != P_TORPOR || agg) update_pos( victim, agg ); return victim->position; } if ( victim == ch ) return ch->position; /* Link dead salvation. */ if ( !IS_NPC(victim) && victim->desc == NULL ) { do_function(victim, &do_flee,""); } tail_chain( ); return victim->position; }
/* Start writing a note */ static void do_nwrite (CHAR_DATA *ch, char *argument) { char *strtime; char buf[200]; if (IS_NPC(ch)) /* NPC cannot post notes */ return; //if ((get_age(ch) - 17) < 2) //{ // send_to_char("Newbies cannot write notes.\n\r",ch); // return; // } if (has_timer(ch)) return; if (IS_SET(ch->act, PLR_SILENCE) ) { send_to_char("You are not allowed to write notes.\n\r",ch); return; } if (ch->pcdata->board == NULL) { send_to_char("You're not on a board.\n\r", ch ); return;} if (get_trust(ch) < ch->pcdata->board->write_level) { send_to_char ("You cannot post notes on this board.\n\r",ch); return; } if (ch->position != POS_STANDING) { send_to_char("You can only write notes while standing.\n\r", ch); return; } /* continue previous note, if any text was written*/ if (ch->pcdata->in_progress && (!ch->pcdata->in_progress->text)) { send_to_char ("Note in progress cancelled because you did not manage to write any text \n\r" "before losing link.\n\r\n\r",ch); free_note (ch->pcdata->in_progress); ch->pcdata->in_progress = NULL; } if (!ch->pcdata->in_progress) { ch->pcdata->in_progress = new_note(); ch->pcdata->in_progress->sender = str_dup (ch->pcdata->switchname); /* convert to ascii. ctime returns a string which last character is \n, so remove that */ strtime = ctime (¤t_time); strtime[strlen(strtime)-1] = '\0'; ch->pcdata->in_progress->date = str_dup (strtime); } SET_BIT(ch->extra, EXTRA_AFK); if (ch->master) stop_follower(ch, FALSE); act (BOLD GREEN "$n starts writing a note." NO_COLOR , ch, NULL, NULL, TO_ROOM); /* Begin writing the note ! */ xprintf (buf, "You are now %s a new note on the " BOLD "%s" NO_COLOR " board.\n\r" "If you are using tintin, type #verbose to turn off alias expansion!\n\r\n\r", ch->pcdata->in_progress->text ? "continuing" : "posting", ch->pcdata->board->short_name); send_to_char (buf,ch); xprintf (buf, BOLD YELLOW "From" NO_COLOR ": %s\n\r\n\r", ch->pcdata->switchname); send_to_char (buf,ch); if (!ch->pcdata->in_progress->text) /* Are we continuing an old note or not? */ { switch (ch->pcdata->board->force_type) { case DEF_NORMAL: xprintf (buf, "If you press Return, default recipient \"" BOLD "%s" NO_COLOR "\" will be chosen.\n\r", ch->pcdata->board->names); break; case DEF_INCLUDE: xprintf (buf, "The recipient list MUST include \"" BOLD "%s" NO_COLOR "\". If not, it will be added automatically.\n\r", ch->pcdata->board->names); break; case DEF_EXCLUDE: xprintf (buf, "The recipient of this note must NOT include: \"" BOLD "%s" NO_COLOR "\".", ch->pcdata->board->names); break; } send_to_char (buf,ch); send_to_char ("\n\r" BOLD YELLOW "To" NO_COLOR ": ",ch); ch->desc->connected = CON_NOTE_TO; /* nanny takes over from here */ } else /* we are continuing, print out all the fields and the note so far*/ { xprintf (buf, BOLD YELLOW "To" NO_COLOR ": %s\n\r" BOLD YELLOW "Expires" NO_COLOR ": %s\n\r" BOLD YELLOW "Subject" NO_COLOR ": %s\n\r", ch->pcdata->in_progress->to_list, ctime(&ch->pcdata->in_progress->expire), ch->pcdata->in_progress->subject); send_to_char (buf,ch); send_to_char (BOLD GREEN "Your note so far:\n\r" NO_COLOR,ch); if (ch->pcdata->in_progress != NULL) send_to_char (ch->pcdata->in_progress->text,ch); send_to_char ("\n\rEnter text. Type " BOLD "~" NO_COLOR " or " BOLD "END" NO_COLOR " on an empty line to end note.\n\r" "=======================================================\n\r",ch); ch->desc->connected = CON_NOTE_TEXT; } }
/* the main engine of charm spell, and similar */ void effect_charm(struct char_data *ch, struct char_data *victim, int spellnum) { struct affected_type af; int elf_bonus = 0; if (!IS_NPC(victim) && (GET_RACE(victim) == RACE_ELF || //elven enchantment resistance GET_RACE(victim) == RACE_H_ELF)) // added check for IS_NPC because NPCRACE_HUMAN == RACE_ELF and NPCRACE_ABERRATION == RACE_H_ELF elf_bonus += 2; if (victim == ch) send_to_char(ch, "You like yourself even better!\r\n"); else if (MOB_FLAGGED(victim, MOB_NOCHARM)) { send_to_char(ch, "Your victim doesn't seem vulnerable to this " "enchantments!\r\n"); if (IS_NPC(victim)) hit(victim, ch, TYPE_UNDEFINED, DAM_RESERVED_DBC, 0, FALSE); } else if (IS_AFFECTED(victim, AFF_MIND_BLANK)) { send_to_char(ch, "Your victim is protected from this " "enchantment!\r\n"); if (IS_NPC(victim)) hit(victim, ch, TYPE_UNDEFINED, DAM_RESERVED_DBC, 0, FALSE); } else if (AFF_FLAGGED(ch, AFF_CHARM)) send_to_char(ch, "You can't have any followers of your own!\r\n"); else if (AFF_FLAGGED(victim, AFF_CHARM)) send_to_char(ch, "Your victim is already charmed.\r\n"); else if (spellnum == SPELL_CHARM && (CASTER_LEVEL(ch) < GET_LEVEL(victim) || GET_LEVEL(victim) >= 8)) send_to_char(ch, "Your victim is too powerful.\r\n"); else if ((spellnum == SPELL_DOMINATE_PERSON || spellnum == SPELL_MASS_DOMINATION) && CASTER_LEVEL(ch) < GET_LEVEL(victim)) send_to_char(ch, "Your victim is too powerful.\r\n"); /* player charming another player - no legal reason for this */ else if (!CONFIG_PK_ALLOWED && !IS_NPC(victim)) send_to_char(ch, "You fail - shouldn't be doing it anyway.\r\n"); else if (circle_follow(victim, ch)) send_to_char(ch, "Sorry, following in circles is not allowed.\r\n"); else if (mag_resistance(ch, victim, 0)) { send_to_char(ch, "You failed to penetrate the spell resistance!"); if (IS_NPC(victim)) hit(victim, ch, TYPE_UNDEFINED, DAM_RESERVED_DBC, 0, FALSE); } else if (mag_savingthrow(ch, victim, SAVING_WILL, elf_bonus)) { send_to_char(ch, "Your victim resists!\r\n"); if (IS_NPC(victim)) hit(victim, ch, TYPE_UNDEFINED, DAM_RESERVED_DBC, 0, FALSE); } else { /* slippery mind gives a second save */ if (!IS_NPC(victim) && GET_SKILL(victim, SKILL_SLIPPERY_MIND)) { increase_skill(victim, SKILL_SLIPPERY_MIND); send_to_char(victim, "\tW*Slippery Mind*\tn "); if (mag_savingthrow(ch, victim, SAVING_WILL, 0)) { return; } } if (victim->master) stop_follower(victim); add_follower(victim, ch); new_affect(&af); if (spellnum == SPELL_CHARM) af.spell = SPELL_CHARM; if (spellnum == SPELL_CHARM_ANIMAL) af.spell = SPELL_CHARM_ANIMAL; else if (spellnum == SPELL_DOMINATE_PERSON) af.spell = SPELL_DOMINATE_PERSON; else if (spellnum == SPELL_MASS_DOMINATION) af.spell = SPELL_MASS_DOMINATION; af.duration = 100; if (GET_CHA_BONUS(ch)) af.duration += GET_CHA_BONUS(ch) * 4; SET_BIT_AR(af.bitvector, AFF_CHARM); affect_to_char(victim, &af); act("Isn't $n just such a nice fellow?", FALSE, ch, 0, victim, TO_VICT); // if (IS_NPC(victim)) // REMOVE_BIT_AR(MOB_FLAGS(victim), MOB_SPEC); } // should never get here }
void mobile_activity(void) { struct char_data *ch, *next_ch, *vict; struct obj_data *obj, *best_obj; int door, found, max; memory_rec *names; for (ch = character_list; ch; ch = next_ch) { next_ch = ch->next; if (!IS_MOB(ch)) continue; /* Examine call for special procedure */ if (MOB_FLAGGED(ch, MOB_SPEC) && !no_specials) { if (mob_index[GET_MOB_RNUM(ch)].func == NULL) { log("SYSERR: %s (#%d): Attempting to call non-existing mob function.", GET_NAME(ch), GET_MOB_VNUM(ch)); REMOVE_BIT_AR(MOB_FLAGS(ch), MOB_SPEC); } else { char actbuf[MAX_INPUT_LENGTH] = ""; if ((mob_index[GET_MOB_RNUM(ch)].func) (ch, ch, 0, actbuf)) continue; /* go to next char */ } } /* If the mob has no specproc, do the default actions */ if (FIGHTING(ch) || !AWAKE(ch)) continue; /* hunt a victim, if applicable */ hunt_victim(ch); /* Scavenger (picking up objects) */ if (MOB_FLAGGED(ch, MOB_SCAVENGER)) if (world[IN_ROOM(ch)].contents && !rand_number(0, 10)) { max = 1; best_obj = NULL; for (obj = world[IN_ROOM(ch)].contents; obj; obj = obj->next_content) if (CAN_GET_OBJ(ch, obj) && GET_OBJ_COST(obj) > max) { best_obj = obj; max = GET_OBJ_COST(obj); } if (best_obj != NULL) { obj_from_room(best_obj); obj_to_char(best_obj, ch); act("$n gets $p.", FALSE, ch, best_obj, 0, TO_ROOM); } } /* Mob Movement */ if (!MOB_FLAGGED(ch, MOB_SENTINEL) && (GET_POS(ch) == POS_STANDING) && ((door = rand_number(0, 18)) < DIR_COUNT) && CAN_GO(ch, door) && !ROOM_FLAGGED(EXIT(ch, door)->to_room, ROOM_NOMOB) && !ROOM_FLAGGED(EXIT(ch, door)->to_room, ROOM_DEATH) && (!MOB_FLAGGED(ch, MOB_STAY_ZONE) || (world[EXIT(ch, door)->to_room].zone == world[IN_ROOM(ch)].zone))) { /* If the mob is charmed, do not move the mob. */ if (ch->master == NULL) perform_move(ch, door, 1); } /* Aggressive Mobs */ if (!MOB_FLAGGED(ch, MOB_HELPER) && (!AFF_FLAGGED(ch, AFF_BLIND) || !AFF_FLAGGED(ch, AFF_CHARM))) { found = FALSE; for (vict = world[IN_ROOM(ch)].people; vict && !found; vict = vict->next_in_room) { if (IS_NPC(vict) || !CAN_SEE(ch, vict) || PRF_FLAGGED(vict, PRF_NOHASSLE)) continue; if (MOB_FLAGGED(ch, MOB_WIMPY) && AWAKE(vict)) continue; if (MOB_FLAGGED(ch, MOB_AGGRESSIVE ) || (MOB_FLAGGED(ch, MOB_AGGR_EVIL ) && IS_EVIL(vict)) || (MOB_FLAGGED(ch, MOB_AGGR_NEUTRAL) && IS_NEUTRAL(vict)) || (MOB_FLAGGED(ch, MOB_AGGR_GOOD ) && IS_GOOD(vict))) { /* Can a master successfully control the charmed monster? */ if (aggressive_mob_on_a_leash(ch, ch->master, vict)) continue; hit(ch, vict, TYPE_UNDEFINED); found = TRUE; } } } /* Mob Memory */ if (MOB_FLAGGED(ch, MOB_MEMORY) && MEMORY(ch)) { found = FALSE; for (vict = world[IN_ROOM(ch)].people; vict && !found; vict = vict->next_in_room) { if (IS_NPC(vict) || !CAN_SEE(ch, vict) || PRF_FLAGGED(vict, PRF_NOHASSLE)) continue; for (names = MEMORY(ch); names && !found; names = names->next) { if (names->id != GET_IDNUM(vict)) continue; /* Can a master successfully control the charmed monster? */ if (aggressive_mob_on_a_leash(ch, ch->master, vict)) continue; found = TRUE; act("'Hey! You're the fiend that attacked me!!!', exclaims $n.", FALSE, ch, 0, 0, TO_ROOM); hit(ch, vict, TYPE_UNDEFINED); } } } /* Charmed Mob Rebellion: In order to rebel, there need to be more charmed * monsters than the person can feasibly control at a time. Then the * mobiles have a chance based on the charisma of their leader. * 1-4 = 0, 5-7 = 1, 8-10 = 2, 11-13 = 3, 14-16 = 4, 17-19 = 5, etc. */ if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && num_followers_charmed(ch->master) > (GET_CHA(ch->master) - 2) / 3) { if (!aggressive_mob_on_a_leash(ch, ch->master, ch->master)) { if (CAN_SEE(ch, ch->master) && !PRF_FLAGGED(ch->master, PRF_NOHASSLE)) hit(ch, ch->master, TYPE_UNDEFINED); stop_follower(ch); } } /* Helper Mobs */ if (MOB_FLAGGED(ch, MOB_HELPER) && (!AFF_FLAGGED(ch, AFF_BLIND) || !AFF_FLAGGED(ch, AFF_CHARM))) { found = FALSE; for (vict = world[IN_ROOM(ch)].people; vict && !found; vict = vict->next_in_room) { if (ch == vict || !IS_NPC(vict) || !FIGHTING(vict)) continue; if (IS_NPC(FIGHTING(vict)) || ch == FIGHTING(vict)) continue; act("$n jumps to the aid of $N!", FALSE, ch, 0, vict, TO_ROOM); hit(ch, FIGHTING(vict), TYPE_UNDEFINED); found = TRUE; } } /* Add new mobile actions here */ } /* end for() */ }
void damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype) { char buf[MAX_STRING_LENGTH]; struct message_type *messages; int i,j,nr,max_hit,exp; int hit_limit(struct char_data *ch); assert(GET_POS(victim) > POSITION_DEAD); if ((GET_LEVEL(victim)>20) && !IS_NPC(victim)) /* You can't damage an immortal! */ dam=0; if (victim != ch) { if (GET_POS(victim) > POSITION_STUNNED) { if (!(victim->specials.fighting)) set_fighting(victim, ch); GET_POS(victim) = POSITION_FIGHTING; } if (GET_POS(ch) > POSITION_STUNNED) { if (!(ch->specials.fighting)) set_fighting(ch, victim); if (IS_NPC(ch) && IS_NPC(victim) && victim->master && !number(0,10) && IS_AFFECTED(victim, AFF_CHARM) && (victim->master->in_room == ch->in_room)) { if (ch->specials.fighting) stop_fighting(ch); hit(ch, victim->master, TYPE_UNDEFINED); return; } } } if (victim->master == ch) stop_follower(victim); if (IS_AFFECTED(ch, AFF_INVISIBLE)) appear(ch); if (IS_AFFECTED(victim, AFF_SANCTUARY)) dam = MIN(dam, 18); /* Max 18 damage when sanctuary */ dam=MIN(dam,100); dam=MAX(dam,0); GET_HIT(victim)-=dam; if (ch != victim) gain_exp(ch,GET_LEVEL(victim)*dam); update_pos(victim); if ((attacktype >= TYPE_HIT) && (attacktype <= TYPE_SLASH)) { if (!ch->equipment[WIELD]) { dam_message(dam, ch, victim, TYPE_HIT); } else { dam_message(dam, ch, victim, attacktype); } } else { for(i = 0; i < MAX_MESSAGES; i++) { if (fight_messages[i].a_type == attacktype) { nr=dice(1,fight_messages[i].number_of_attacks); for(j=1,messages=fight_messages[i].msg;(j<nr)&&(messages);j++) messages=messages->next; if (!IS_NPC(victim) && (GET_LEVEL(victim) > 20)) { act(messages->god_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR); act(messages->god_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT); act(messages->god_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT); } else if (dam != 0) { if (GET_POS(victim) == POSITION_DEAD) { act(messages->die_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR); act(messages->die_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT); act(messages->die_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT); } else { act(messages->hit_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR); act(messages->hit_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT); act(messages->hit_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT); } } else { /* Dam == 0 */ act(messages->miss_msg.attacker_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_CHAR); act(messages->miss_msg.victim_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_VICT); act(messages->miss_msg.room_msg, FALSE, ch, ch->equipment[WIELD], victim, TO_NOTVICT); } } } } switch (GET_POS(victim)) { case POSITION_MORTALLYW: act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, TO_ROOM); act("You are mortally wounded, and will die soon, if not aided.", FALSE, victim, 0, 0, TO_CHAR); break; case POSITION_INCAP: act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, TO_ROOM); act("You are incapacitated an will slowly die, if not aided.", FALSE, victim, 0, 0, TO_CHAR); break; case POSITION_STUNNED: act("$n is stunned, but will probably regain conscience again.", TRUE, victim, 0, 0, TO_ROOM); act("You're stunned, but will probably regain conscience again.", FALSE, victim, 0, 0, TO_CHAR); break; case POSITION_DEAD: act("$n is dead! R.I.P.", TRUE, victim, 0, 0, TO_ROOM); act("You are dead! Sorry...", FALSE, victim, 0, 0, TO_CHAR); break; default: /* >= POSITION SLEEPING */ max_hit=hit_limit(victim); if (dam > (max_hit/5)) act("That Really did HURT!",FALSE, victim, 0, 0, TO_CHAR); if (GET_HIT(victim) < (max_hit/5)) { act("You wish that your wounds would stop BLEEDING that much!",FALSE,victim,0,0,TO_CHAR); if (IS_NPC(victim)) if (IS_SET(victim->specials.act, ACT_WIMPY)) do_flee(victim, "", 0); } break; } if (!IS_NPC(victim) && !(victim->desc)) { do_flee(victim, "", 0); if (!victim->specials.fighting) { act("$n is rescued by divine forces.", FALSE, victim, 0, 0, TO_ROOM); victim->specials.was_in_room = victim->in_room; char_from_room(victim); char_to_room(victim, 0); } } if (GET_POS(victim) < POSITION_STUNNED) if (ch->specials.fighting == victim) stop_fighting(ch); if (!AWAKE(victim)) if (victim->specials.fighting) stop_fighting(victim); if (GET_POS(victim) == POSITION_DEAD) { if (IS_NPC(victim) || victim->desc) if (IS_AFFECTED(ch, AFF_GROUP)) { group_gain(ch, victim); } else { /* Calculate level-difference bonus */ exp = GET_EXP(victim)/3; if (IS_NPC(ch)) exp += (exp*MIN(4, (GET_LEVEL(victim) - GET_LEVEL(ch))))>>3; else exp += (exp*MIN(8, (GET_LEVEL(victim) - GET_LEVEL(ch))))>>3; exp = MAX(exp, 1); gain_exp(ch, exp); change_alignment(ch, victim); } if (!IS_NPC(victim)) { sprintf(buf, "%s killed by %s at %s", GET_NAME(victim), (IS_NPC(ch) ? ch->player.short_descr : GET_NAME(ch)), world[victim->in_room].name); log(buf); } die(victim); }