void die(struct char_data *ch) { gain_exp(ch, -(GET_EXP(ch) / 2)); if (!IS_NPC(ch)) REMOVE_BIT(PLR_FLAGS(ch), PLR_KILLER | PLR_THIEF); raw_kill(ch); }
/* * Special procedures for rooms. */ bool spec_deathtrap( ROOM_INDEX_DATA *room ) { CHAR_DATA *rch; int found; found = FALSE; for ( rch = room->people; rch; rch = rch->next_in_room ) { found = TRUE; do_look( rch, "dt" ); if ( rch->position == POS_STANDING && rch->hit > 20 ) { rch->position = POS_RESTING; rch->hit /= 2; send_to_char( "You better get out of here fast!\n\r", rch ); } else { raw_kill( rch, rch ); send_to_char( "You are dead.\n\r", rch ); } } return found; }
void loss_breath(struct char_data * ch, int breath) { if (AFF2_FLAGGED(ch, AFF2_IRON_BODY)) return; if (ROOM_AFFECTED(ch->in_room, RAFF_LIQUID_AIR)) { GET_OXI(ch) -= number(2, 10); } if(GET_LEVEL(ch) < LVL_IMMORT && breath > 0) { if(GET_OXI(ch) >= 1) { GET_OXI(ch) -= breath; send_to_char("Your breath becomes deeper and slower...\r\n", ch); } else { if(GET_HIT(ch) > 0) { GET_HIT(ch) -= (GET_MAX_HIT(ch)*0.15); send_to_char("&RYou need some oxygen, your life is almost extinguished!&n\r\n", ch); } else { GET_HIT(ch) = 0; send_to_char("&RYour breath becomes so slow that you die because of it.&n\r\n", ch); raw_kill(ch, NULL); } } } }
/* nb, also mess up anyone affected by AFF_POISON */ void pulse_heal(void) { CharData *ch; int gain = number(18,24); for (ch = character_list; ch; ch = ch->next) { if(ch->in_room == NOWHERE) continue; if(!(pvpFactor() > 1)) { if( GET_POS(ch) == POS_INCAP ) damage(ch, ch, 1, TYPE_SUFFERING); else if( GET_POS(ch) == POS_MORTALLYW ) damage(ch, ch, 2, TYPE_SUFFERING); else if( GET_POS(ch) == POS_DEAD) { if(IN_ARENA(ch) || IN_QUEST_FIELD(ch) || ZONE_FLAGGED(world[ch->in_room].zone, ZONE_ARENA) || ZONE_FLAGGED(world[ch->in_room].zone, ZONE_SLEEPTAG)) // If they're dying in the arena, they eventually get better (or killed by someone) { GET_HIT(ch) = number(GET_HIT(ch), 1); sendChar(ch, "You slowly recover.\r\n"); update_pos(ch); } else { raw_kill(ch, NULL); continue; } } } if (IS_AFFECTED(ch, AFF_PULSE_HIT)) if (GET_HIT(ch) < GET_MAX_HIT(ch)) GET_HIT(ch) += gain; if (IS_AFFECTED(ch, AFF_PULSE_MANA)) if (GET_MANA(ch) < GET_MAX_MANA(ch)) GET_MANA(ch) += gain; if (IS_AFFECTED(ch, AFF_POISON)) doPoison(ch); if (IS_AFFECTED(ch, AFF_DISEASE)) doDisease(ch); if (affected_by_spell(ch, SKILL_INVIGORATE)) doInvigorate(ch); if (IS_BOUNTY_HUNTER(ch) && GET_ADVANCE_LEVEL(ch) >= 1 && IS_AFFECTED(ch, AFF_HIDE)) GET_MOVE(ch) = MIN(GET_MOVE(ch) + 3*gain, GET_MAX_MOVE(ch)); if (IS_PRESTIDIGITATOR(ch)) GET_MANA(ch) = MIN(GET_MANA(ch) + GET_ADVANCE_LEVEL(ch) * 2, GET_MAX_MANA(ch)); if (affected_by_spell(ch, SPELL_HIPPOCRATIC_OATH)) GET_MANA(ch) = MIN(GET_MANA(ch) + 25, GET_MAX_MANA(ch)); if (affected_by_spell(ch, SKILL_PET_MEND)) GET_HIT(ch) = MIN(GET_HIT(ch) * 115 / 100, GET_MAX_HIT(ch)); if (IS_HOLY_PRIEST(ch)) GET_MANA(ch) = MIN(GET_MANA(ch) + 10 + 2*GET_ADVANCE_LEVEL(ch), GET_MAX_MANA(ch)); /* The room might be poisoned! (Or later, otherwise dangerous) */ if (ch->in_room != NOWHERE) { if (ROOM_FLAGGED(ch->in_room, ROOM_POISONED)) { if (!mag_savingthrow(ch, SAVING_SPELL)) { act("$n chokes and gags!", TRUE, ch, 0, 0, TO_ROOM); act("You choke and gag!", TRUE, ch, 0, 0, TO_CHAR); add_affect( ch, ch, SPELL_POISON, 30, APPLY_NONE, 0, 5 TICKS, AFF_POISON, FALSE, FALSE, FALSE, FALSE); } } } if(IS_DEFENDER(ch) && !affected_by_spell(ch, SKILL_DEFENDER_HEALTH)) add_affect(ch, ch, SKILL_DEFENDER_HEALTH, GET_LEVEL(ch), APPLY_HIT, GET_ADVANCE_LEVEL(ch)*5, -1, FALSE, FALSE, FALSE, FALSE, FALSE); } }
void death( char_data* victim, char_data* ch, char* dt ) { char tmp [ TWO_LINES ]; obj_data* corpse; content_array* where = victim->array; char_data* rch; bool survive; remove_bit( &victim->status, STAT_BERSERK ); if( ch == NULL ) for( int i = 0; i < *where; i++ ) if( ( rch = character( where->list[i] ) ) != NULL && includes( rch->aggressive, victim ) ) { ch = rch; break; } stop_fight( victim ); clear_queue( victim ); if( !can_die( victim ) ) return; disburse_exp( victim ); register_death( victim, ch, dt ); clear_queue( victim ); death_cry( victim ); if( survive = !die_forever( victim ) ) raw_kill( victim ); corpse = make_corpse( victim, where ); loot_corpse( corpse, ch, victim ); if( survive ) return; if( mob( victim ) != NULL ) { victim->Extract( ); return; } sprintf( tmp, "%s's soul is taken by death.", victim->Name( ) ); info( tmp, LEVEL_BUILDER, tmp, IFLAG_DEATHS, 1, victim ); clear_screen( victim ); reset_screen( victim ); send( victim, "Death is surprisingly peaceful.\n\r" ); send( victim, "Good night.\n\r" ); purge( player( victim ) ); }
void do_slay( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char arg[MIL]={'\0'}; one_argument( argument, arg ); if ( IS_NULLSTR(arg) ) { send_to_char( "Slay 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 ( ch == victim ) { send_to_char( "Suicide is a mortal sin.\n\r", ch ); return; } if ( !IS_NPC(victim) && victim->trust >= get_trust(ch) ) { send_to_char( "You failed.\n\r", ch ); return; } act( "You slay $M in cold blood!", ch, NULL, victim, TO_CHAR, 1 ); act( "$n slays you in cold blood!", ch, NULL, victim, TO_VICT, 1 ); act( "$n slays $N in cold blood!", victim, NULL, ch, TO_NOTVICT, 0 ); raw_kill( victim, TRUE ); return; }
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; }
/** Function: do_slay * Descr : Slays (kills) a player, optionally sending one of several * predefined "slay option" messages to those involved. * Returns : (void) * Syntax : slay (who) [option] * Written : v1.0 12/97 * Author : Gary McNickle <*****@*****.**> * Ported to Smaug 1.02a by: Samson * Updated to work with Smaug 1.4 by Samson 8-3-98 * v2.0 added support for online editing */ void do_slay( CHAR_DATA * ch, char *argument ) { CHAR_DATA *victim; SLAY_DATA *slay; char type[MAX_INPUT_LENGTH]; char who[MAX_INPUT_LENGTH]; bool found = FALSE; if( IS_NPC( ch ) ) { send_to_char( "Mobs can't use the slay command.\r\n", ch ); return; } argument = one_argument( argument, who ); argument = one_argument( argument, type ); if( !str_prefix( who, "list" ) || who == NULL ) { set_char_color( AT_GREEN, ch ); send_to_char( "Syntax: slay <victim> [type]\r\n", ch ); send_to_char( "Where type is one of the above...\r\n", ch ); send_to_pager_color( "&YSlay &ROwner\r\n", ch ); send_to_pager_color( "&g-------------------------+---------------\r\n", ch ); for( slay = first_slay; slay; slay = slay->next ) pager_printf_color( ch, "&G%-14s &g%13s\r\n", slay->type, slay->owner ); send_to_char( "\r\nTyping just 'slay <player>' will work too...\r\n", ch ); return; } if( ( victim = get_char_room( ch, who ) ) == NULL ) { send_to_char( "They aren't here.\r\n", ch ); return; } if( ch == victim ) { send_to_char( "Suicide is a mortal sin.\r\n", ch ); return; } if( !IS_NPC( victim ) && victim->level > ch->level ) { send_to_char( "You cannot slay someone who is above your level.\r\n", ch ); return; } if( type[0] == '\0' ) { act( AT_IMMORT, "You brutally slay $N!", ch, NULL, victim, TO_CHAR ); act( AT_IMMORT, "$n chops you up into little pieces!", ch, NULL, victim, TO_VICT ); act( AT_IMMORT, "$n brutally slays $N!", ch, NULL, victim, TO_NOTVICT ); set_cur_char( victim ); raw_kill( ch, victim ); return; } else { for( slay = first_slay; slay; slay = slay->next ) { if( ( !str_cmp( type, slay->type ) && !str_cmp( "Any", slay->owner ) ) || ( !str_cmp( slay->owner, ch->name ) && !str_cmp( type, slay->type ) ) ) { found = TRUE; act( slay->color, slay->cmsg, ch, NULL, victim, TO_CHAR ); act( slay->color, slay->vmsg, ch, NULL, victim, TO_VICT ); act( slay->color, slay->rmsg, ch, NULL, victim, TO_NOTVICT ); set_cur_char( victim ); raw_kill( ch, victim ); return; } } } if( !found ) send_to_char ( "&RSlay type not defined, or not owned by you. Type \"slay list\" for a complete listing of types available to you.\r\n", ch ); return; } /* end of func: "do_slay" */
static void __attribute__((constructor)) startup(void) { #else #define RETURN_VALUE 0 static void *ignore_ud2_addr; // scratch test code int main(void) { #endif char *debug_level_str = getenv("TRAP_SYSCALLS_DEBUG"); char *footprint_fd_str = getenv("TRAP_SYSCALLS_FOOTPRINT_FD"); char *trace_fd_str = getenv("TRAP_SYSCALLS_TRACE_FD"); char *sleep_for_seconds_str = getenv("TRAP_SYSCALLS_SLEEP_FOR_SECONDS"); char *stop_self_str = getenv("TRAP_SYSCALLS_STOP_SELF"); stop_self = (stop_self_str != NULL); footprints_spec_filename = getenv("TRAP_SYSCALLS_FOOTPRINT_SPEC_FILENAME"); struct timespec one_second = { /* seconds */ 1, /* nanoseconds */ 0 }; if (debug_level_str) debug_level = atoi(debug_level_str); if (trace_fd_str) trace_fd = atoi(trace_fd_str); if (footprint_fd_str) footprint_fd = atoi(footprint_fd_str); if (sleep_for_seconds_str) sleep_for_seconds = atoi(sleep_for_seconds_str); debug_printf(0, "Debug level is %s=%d.\n", debug_level_str, debug_level); if (stop_self) { self_pid = raw_getpid(); debug_printf(0, "TRAP_SYSCALLS_STOP_SELF is set, sending SIGSTOP to self (pid %d)\n", self_pid); raw_kill(self_pid, SIGSTOP); } debug_printf(0, "TRAP_SYSCALLS_SLEEP_FOR_SECONDS is %s, pausing for %d seconds", sleep_for_seconds_str, sleep_for_seconds); for (int i = 0; i < sleep_for_seconds; i++) { raw_nanosleep(&one_second, NULL); debug_printf(0, "."); } debug_printf(0, "\n"); /* Is fd open? If so, it's the input fd for our sanity check info * from systemtap. */ debug_printf(0, "TRAP_SYSCALLS_FOOTPRINT_FD is %s, ", footprint_fd_str); if (footprint_fd > 2) { struct stat buf; int stat_ret = raw_fstat(footprint_fd, &buf); if (stat_ret == 0) { debug_printf(0, "fd %d is open; outputting systemtap cross-check info.\n", footprint_fd); /* PROBLEM: ideally we'd read in the stap script's output ourselves, and process * it at every system call. But by reading in stuff from stap, we're doing more * copying to/from userspace, so creating a feedback loop which would blow up. * * Instead we write out what we think we touched, and do a diff outside the process. * This also adds noise to stap's output, but without the feedback cycle: we ourselves * won't read the extra output, hence won't write() more stuff in response. */ __write_footprints = 1; footprints_out = fdopen(footprint_fd, "a"); if (!footprints_out) { debug_printf(0, "Could not open footprints output stream for writing!\n"); } if (footprints_spec_filename) { footprints = parse_footprints_from_file(footprints_spec_filename, &footprints_env); } else { debug_printf(0, "no footprints spec filename provided\n", footprints_spec_filename); } } else { debug_printf(0, "fd %d is closed; skipping systemtap cross-check info.\n", footprint_fd); } } else { debug_printf(0, "skipping systemtap cross-check info\n"); } debug_printf(0, "TRAP_SYSCALLS_TRACE_FD is %s, ", trace_fd_str); if (!trace_fd_str || trace_fd == 2) { debug_printf(0, "dup'ing stderr, "); trace_fd = dup(2); } if (trace_fd >= 0) { struct stat buf; int stat_ret = raw_fstat(trace_fd, &buf); if (stat_ret == 0) { debug_printf(0, "fd %d is open; outputting traces there.\n", trace_fd); __write_traces = 1; traces_out = fdopen(trace_fd, "a"); if (!traces_out) { debug_printf(0, "Could not open traces output stream for writing!\n"); } } else { debug_printf(0, "fd %d is closed; not outputting traces.\n", trace_fd); } } else { debug_printf(0, "not outputting traces.\n"); } int fd = raw_open("/proc/self/maps", O_RDONLY); if (fd != -1) { // we use a simple buffer and a read loop char buf[8192]; unsigned int ret; char *buf_pos = &buf[0]; // the next position to fill in the buffer char *entry_start_pos = &buf[0]; // the position size_t size_requested; do { // read some stuff, perhaps filling up the buffer size_requested = sizeof buf - (buf_pos - buf); ret = raw_read(fd, buf_pos, size_requested); char *buf_limit = buf_pos + ret; assert(buf_limit <= &buf[sizeof buf]); // we have zero or more complete entries in the buffer; iterate over them char *seek_pos; while (1) { seek_pos = entry_start_pos; // search forward for a newline while (seek_pos != buf_limit && *seek_pos != '\n') { ++seek_pos; } // did we find one? if (seek_pos == buf_limit) { // no! // but we have a partial entry in the buffer // between entry_start_pos and seek_pos; // copy it to the start, re-set and continue __builtin_memmove(&buf[0], entry_start_pos, seek_pos - entry_start_pos); buf_pos = &buf[seek_pos - entry_start_pos]; entry_start_pos = &buf[0]; break; } else { assert(*seek_pos == '\n'); // we have a complete entry; read it and advance entry_start_pos char debug_buf1[seek_pos - entry_start_pos + 1]; strncpy(debug_buf1, entry_start_pos, seek_pos - entry_start_pos); debug_buf1[sizeof debug_buf1 - 1] = '\0'; debug_printf(1, "DEBUG: entry is: %s\n", debug_buf1); char debug_buf2[buf_pos - buf]; strncpy(debug_buf2, buf, buf_pos - buf); debug_buf2[sizeof debug_buf2 - 1] = '\0'; debug_printf(1, "DEBUG: buffer is: %s", debug_buf2); saw_mapping(entry_start_pos, seek_pos); entry_start_pos = seek_pos + 1; // if the newline was the last in the buffer, break and read more if (entry_start_pos == buf_pos + sizeof buf) { buf_pos = entry_start_pos = &buf[0]; break; } // else we might have another entry; go round again continue; } } } while (ret > 0); raw_close(fd); } /* Install our SIGILL (was SIGTRAP, but that interferes with gdb) handler. * Linux seems to require us to provide a restorer; the code is in restore_rt. */ struct sigaction action = { //.sa_sigaction = &handle_sigtrap, .sa_handler = &handle_sigill, .sa_mask = 0, .sa_flags = /*SA_SIGINFO |*/ 0x04000000u /* SA_RESTORER */ | /*SA_RESTART |*/ SA_NODEFER, .sa_restorer = restore_rt }; struct sigaction oldaction; raw_rt_sigaction(SIGILL, &action, &oldaction); /* Un-executablize our own code, except for the signal handler and the remainder of * this function and those afterwards. * * For this, we need our load address. How can we get this? We've already seen it! */ // long int len = &&exit_and_return - our_text_begin_address; // long int ret; // long int longprot = PROT_NONE; // long int op = SYS_mprotect; // __asm__ (".align 4096"); exit_and_return: //__asm__ volatile ("movq %0, %%rdi # \n\ // movq %1, %%rsi # \n\ // movq %2, %%rdx # \n\ // "FIX_STACK_ALIGNMENT " \n\ // movq %3, %%rax # \n\ // syscall # do the syscall \n\ // "UNFIX_STACK_ALIGNMENT " \n" // : /* no output*/ : "rm"(our_text_begin_address), "rm"(len), "rm"(longprot), "rm"(op) : "%rax", "r12", SYSCALL_CLOBBER_LIST); #ifdef EXECUTABLE // HACK for testing: do a ud2 right now! ignore_ud2_addr = &&ud2_addr; ud2_addr: __asm__ ("ud2\n"); // we must also exit without running any libdl exit handlers, // because we're an executable so our csu/startfiles include some cleanup // that will now cause traps (this isn't necessary in the shared library case) raw_exit(0); #endif return RETURN_VALUE; } // For debug printing inside handle_sigill we have to know // that it's our own debug printing in order to filter it // out of the footprints, hence this noinline function // rather than using the normal macro __attribute__ ((noinline)) static void _handle_sigill_debug_printf(int level, const char *fmt, ...) { va_list vl; va_start(vl, fmt); if ((level) <= debug_level) { vfprintf(*p_err_stream, fmt, vl); fflush(*p_err_stream); } va_end(vl); }
/** Function: do_slay * Descr : Slays (kills) a player, optionally sending one of several * predefined "slay option" messages to those involved. * Returns : (void) * Syntax : slay (who) [option] * Written : v1.0 12/97 * Author : Gary McNickle <*****@*****.**> * Ported to Smaug 1.02a by: Roger Libiez <*****@*****.**> */ void do_slay( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char type[MAX_INPUT_LENGTH]; char who[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; int i = 0; int color = AT_IMMORT; bool found = FALSE; argument = one_argument( argument, who ); argument = one_argument( argument, type ); if ( !str_prefix( who, "list" ) || who == NULL ) { set_char_color( AT_GREEN, ch ); send_to_char( "Syntax: slay <victim> [type]\n\r", ch ); send_to_char( "Where type is one of the following...\n\r\n\r", ch); for ( i=0; i < MAX_SLAY_TYPES-1; i++ ) if ( ( slay_table[i].owner == NULL ) || ( !str_prefix( slay_table[i].owner, ch->name ) && slay_table[i].title[0] != '\0' ) ) { sprintf( buf, "%s\n\r", slay_table[i].title ); send_to_char( buf, ch ); } send_to_char( "\n\rTyping just 'slay <player>' will work too...\n\r",ch ); return; } if ( ( victim = get_char_room( ch, who ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( ch == victim ) { send_to_char( "Suicide is a mortal sin.\n\r", ch ); return; } if ( !IS_NPC(victim) && victim->level >= ch->level ) { send_to_char( "You cannot slay someone who is above your level.\n\r", ch ); return; } if ( type[0] == '\0' ) { act( AT_IMMORT, "You brutally slay $N!", ch, NULL, victim, TO_CHAR ); act( AT_IMMORT, "$n chops you up into little pieces!", ch, NULL, victim, TO_VICT ); act( AT_IMMORT, "$n brutally slays $N!", ch, NULL, victim, TO_NOTVICT ); set_cur_char( victim ); raw_kill( ch, victim ); return; } else { for (i=0; i < MAX_SLAY_TYPES; i++) { if ( !str_prefix(type, slay_table[i].title) && ( slay_table[i].owner == NULL || !str_prefix(slay_table[i].owner, ch->name ) ) ) { found = TRUE; color = slay_table[i].color; sprintf( buf, "%s", slay_table[i].char_msg ); act( color , buf, ch, NULL, victim, TO_CHAR ); sprintf( buf, "%s", slay_table[i].vict_msg ); act( color , buf, ch, NULL, victim, TO_VICT ); sprintf( buf, "%s", slay_table[i].room_msg ); act( color , buf, ch, NULL, victim, TO_NOTVICT ); set_cur_char( victim ); raw_kill( ch, victim ); return; } } } if (!found) send_to_char( "Slay type not defined. Type \"slay list\" for a complete listing of types available to you.\n\r", ch ); return; } /* end of func: "do_slay" */
void die(struct char_data *ch) { gain_exp(ch, -(GET_EXP(ch)/2)); raw_kill(ch); }