void do_mposet( CHAR_DATA * ch, const char *argument ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; OBJ_DATA *obj; char outbuf[MAX_STRING_LENGTH]; int value, tmp; /* * A desc means switched.. too many loopholes if we allow that.. */ if ( !IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ) || ch->desc ) { send_to_char( "Huh?\r\n", ch ); return; } smash_tilde( argument ); argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); mudstrlcpy( arg3, argument, MAX_INPUT_LENGTH ); if ( !*arg1 ) { progbug( "MpOset: no args", ch ); return; } if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL ) { progbug( "MpOset: no object", ch ); return; } if ( IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) ) { progbug( "MpOset: can't set prototype items", ch ); return; } separate_obj( obj ); value = atoi( arg3 ); if ( !str_cmp( arg2, "value0" ) || !str_cmp( arg2, "v0" ) ) { obj->value[0] = value; return; } if ( !str_cmp( arg2, "value1" ) || !str_cmp( arg2, "v1" ) ) { obj->value[1] = value; return; } if ( !str_cmp( arg2, "value2" ) || !str_cmp( arg2, "v2" ) ) { obj->value[2] = value; return; } if ( !str_cmp( arg2, "value3" ) || !str_cmp( arg2, "v3" ) ) { obj->value[3] = value; return; } if ( !str_cmp( arg2, "value4" ) || !str_cmp( arg2, "v4" ) ) { obj->value[4] = value; return; } if ( !str_cmp( arg2, "value5" ) || !str_cmp( arg2, "v5" ) ) { obj->value[5] = value; return; } if ( !str_cmp( arg2, "type" ) ) { if ( !argument || argument[0] == '\0' ) { progbug( "MpOset: no type", ch ); return; } value = get_otype( argument ); if ( value < 1 ) { progbug( "MpOset: Invalid type", ch ); return; } obj->item_type = ( short ) value; return; } if ( !str_cmp( arg2, "flags" ) ) { if ( !argument || argument[0] == '\0' ) { progbug( "MpOset: no flags", ch ); return; } while ( argument[0] != '\0' ) { argument = one_argument( argument, arg3 ); value = get_oflag( arg3 ); if ( value < 0 || value >= MAX_BITS ) progbug( "MpOset: Invalid flag", ch ); else { if ( value == ITEM_PROTOTYPE ) progbug( "MpOset: can't set prototype flag", ch ); else xTOGGLE_BIT( obj->extra_flags, value ); } } return; } if ( !str_cmp( arg2, "wear" ) ) { if ( !argument || argument[0] == '\0' ) { progbug( "MpOset: no wear", ch ); return; } while ( argument[0] != '\0' ) { argument = one_argument( argument, arg3 ); value = get_wflag( arg3 ); if ( value < 0 || value > 31 ) progbug( "MpOset: Invalid wear", ch ); else TOGGLE_BIT( obj->wear_flags, 1 << value ); } return; } if ( !str_cmp( arg2, "level" ) ) { obj->level = value; return; } if ( !str_cmp( arg2, "weight" ) ) { obj->weight = value; return; } if ( !str_cmp( arg2, "cost" ) ) { obj->cost = value; return; } if ( !str_cmp( arg2, "timer" ) ) { obj->timer = value; return; } if ( !str_cmp( arg2, "name" ) ) { STRFREE( obj->name ); obj->name = STRALLOC( arg3 ); return; } if ( !str_cmp( arg2, "short" ) ) { STRFREE( obj->short_descr ); obj->short_descr = STRALLOC( arg3 ); if ( obj == supermob_obj ) { STRFREE( supermob->short_descr ); supermob->short_descr = QUICKLINK( obj->short_descr ); } /* * Feature added by Narn, Apr/96 * * If the item is not proto, add the word 'rename' to the keywords * * if it is not already there. */ if ( str_infix( "mprename", obj->name ) ) { snprintf( buf, MAX_STRING_LENGTH, "%s %s", obj->name, "mprename" ); STRFREE( obj->name ); obj->name = STRALLOC( buf ); } return; } if ( !str_cmp( arg2, "long" ) ) { STRFREE( obj->description ); mudstrlcpy( buf, arg3, MAX_STRING_LENGTH ); obj->description = STRALLOC( buf ); return; } if ( !str_cmp( arg2, "actiondesc" ) ) { if ( strstr( arg3, "%n" ) || strstr( arg3, "%d" ) || strstr( arg3, "%l" ) ) { progbug( "MpOset: Illegal actiondesc", ch ); return; } STRFREE( obj->action_desc ); obj->action_desc = STRALLOC( arg3 ); return; } if ( !str_cmp( arg2, "affect" ) ) { AFFECT_DATA *paf; short loc; int bitv; argument = one_argument( argument, arg2 ); if ( arg2[0] == '\0' || !argument || argument[0] == 0 ) { progbug( "MpOset: Bad affect syntax", ch ); send_to_char( "Usage: oset <object> affect <field> <value>\r\n", ch ); return; } loc = get_atype( arg2 ); if ( loc < 1 ) { progbug( "MpOset: Invalid affect field", ch ); return; } if ( loc >= APPLY_AFFECT && loc < APPLY_WEAPONSPELL ) { bitv = 0; while ( argument[0] != '\0' ) { argument = one_argument( argument, arg3 ); if ( loc == APPLY_AFFECT ) value = get_aflag( arg3 ); else value = get_risflag( arg3 ); if ( value < 0 || value > 31 ) progbug( "MpOset: bad affect flag", ch ); else SET_BIT( bitv, 1 << value ); } if ( !bitv ) return; value = bitv; } else { argument = one_argument( argument, arg3 ); value = atoi( arg3 ); } CREATE( paf, AFFECT_DATA, 1 ); paf->type = -1; paf->duration = -1; paf->location = loc; paf->modifier = value; xCLEAR_BITS( paf->bitvector ); paf->next = NULL; LINK( paf, obj->first_affect, obj->last_affect, next, prev ); ++top_affect; return; } if ( !str_cmp( arg2, "rmaffect" ) ) { AFFECT_DATA *paf; short loc, count; if ( !argument || argument[0] == '\0' ) { progbug( "MpOset: no rmaffect", ch ); return; } loc = atoi( argument ); if ( loc < 1 ) { progbug( "MpOset: Invalid rmaffect", ch ); return; } count = 0; for ( paf = obj->first_affect; paf; paf = paf->next ) { if ( ++count == loc ) { UNLINK( paf, obj->first_affect, obj->last_affect, next, prev ); DISPOSE( paf ); send_to_char( "Removed.\r\n", ch ); --top_affect; return; } } progbug( "MpOset: rmaffect not found", ch ); return; } /* * save some finger-leather */ if ( !str_cmp( arg2, "ris" ) ) { snprintf( outbuf, MAX_STRING_LENGTH, "%s affect resistant %s", arg1, arg3 ); do_mposet( ch, outbuf ); snprintf( outbuf, MAX_STRING_LENGTH, "%s affect immune %s", arg1, arg3 ); do_mposet( ch, outbuf ); snprintf( outbuf, MAX_STRING_LENGTH, "%s affect susceptible %s", arg1, arg3 ); do_mposet( ch, outbuf ); return; } if ( !str_cmp( arg2, "r" ) ) { snprintf( outbuf, MAX_STRING_LENGTH, "%s affect resistant %s", arg1, arg3 ); do_mposet( ch, outbuf ); return; } if ( !str_cmp( arg2, "i" ) ) { snprintf( outbuf, MAX_STRING_LENGTH, "%s affect immune %s", arg1, arg3 ); do_mposet( ch, outbuf ); return; } if ( !str_cmp( arg2, "s" ) ) { snprintf( outbuf, MAX_STRING_LENGTH, "%s affect susceptible %s", arg1, arg3 ); do_mposet( ch, outbuf ); return; } if ( !str_cmp( arg2, "ri" ) ) { snprintf( outbuf, MAX_STRING_LENGTH, "%s affect resistant %s", arg1, arg3 ); do_mposet( ch, outbuf ); snprintf( outbuf, MAX_STRING_LENGTH, "%s affect immune %s", arg1, arg3 ); do_mposet( ch, outbuf ); return; } if ( !str_cmp( arg2, "rs" ) ) { snprintf( outbuf, MAX_STRING_LENGTH, "%s affect resistant %s", arg1, arg3 ); do_mposet( ch, outbuf ); snprintf( outbuf, MAX_STRING_LENGTH, "%s affect susceptible %s", arg1, arg3 ); do_mposet( ch, outbuf ); return; } if ( !str_cmp( arg2, "is" ) ) { snprintf( outbuf, MAX_STRING_LENGTH, "%s affect immune %s", arg1, arg3 ); do_mposet( ch, outbuf ); snprintf( outbuf, MAX_STRING_LENGTH, "%s affect susceptible %s", arg1, arg3 ); do_mposet( ch, outbuf ); return; } /* * Make it easier to set special object values by name than number * -Thoric */ tmp = -1; switch ( obj->item_type ) { case ITEM_WEAPON: if ( !str_cmp( arg2, "weapontype" ) ) { unsigned int x; value = -1; for ( x = 0; x < sizeof( attack_table ) / sizeof( attack_table[0] ); x++ ) if ( !str_cmp( arg3, attack_table[x] ) ) value = x; if ( value < 0 ) { progbug( "MpOset: Invalid weapon type", ch ); return; } tmp = 3; break; } if ( !str_cmp( arg2, "condition" ) ) tmp = 0; break; case ITEM_ARMOR: if ( !str_cmp( arg2, "condition" ) ) tmp = 3; if ( !str_cmp( arg2, "ac" ) ) tmp = 1; break; case ITEM_SALVE: if ( !str_cmp( arg2, "slevel" ) ) tmp = 0; if ( !str_cmp( arg2, "maxdoses" ) ) tmp = 1; if ( !str_cmp( arg2, "doses" ) ) tmp = 2; if ( !str_cmp( arg2, "delay" ) ) tmp = 3; if ( !str_cmp( arg2, "spell1" ) ) tmp = 4; if ( !str_cmp( arg2, "spell2" ) ) tmp = 5; if ( tmp >= 4 && tmp <= 5 ) value = skill_lookup( arg3 ); break; case ITEM_SCROLL: case ITEM_POTION: case ITEM_PILL: if ( !str_cmp( arg2, "slevel" ) ) tmp = 0; if ( !str_cmp( arg2, "spell1" ) ) tmp = 1; if ( !str_cmp( arg2, "spell2" ) ) tmp = 2; if ( !str_cmp( arg2, "spell3" ) ) tmp = 3; if ( tmp >= 1 && tmp <= 3 ) value = skill_lookup( arg3 ); break; case ITEM_STAFF: case ITEM_WAND: if ( !str_cmp( arg2, "slevel" ) ) tmp = 0; if ( !str_cmp( arg2, "spell" ) ) { tmp = 3; value = skill_lookup( arg3 ); } if ( !str_cmp( arg2, "maxcharges" ) ) tmp = 1; if ( !str_cmp( arg2, "charges" ) ) tmp = 2; break; case ITEM_CONTAINER: if ( !str_cmp( arg2, "capacity" ) ) tmp = 0; if ( !str_cmp( arg2, "cflags" ) ) tmp = 1; if ( !str_cmp( arg2, "key" ) ) tmp = 2; break; case ITEM_SWITCH: case ITEM_LEVER: case ITEM_PULLCHAIN: case ITEM_BUTTON: if ( !str_cmp( arg2, "tflags" ) ) { tmp = 0; value = get_trigflag( arg3 ); } break; } if ( tmp >= 0 && tmp <= 3 ) { obj->value[tmp] = value; return; } progbug( "MpOset: Invalid field", ch ); return; }
/* * Hit one guy with a projectile. * Handles use of missile weapons (wield = missile weapon) * or thrown items/weapons */ ch_ret projectile_hit( char_data * ch, char_data * victim, obj_data * wield, obj_data * projectile, short dist ) { int vic_ac, thac0, plusris, diceroll, prof_bonus, prof_gsn = -1, proj_bonus, dt, pchance; double dam = 0; ch_ret retcode; if( !projectile ) return rNONE; if( projectile->item_type == ITEM_PROJECTILE || projectile->item_type == ITEM_WEAPON ) { dt = TYPE_HIT + projectile->value[3]; if( wield ) proj_bonus = number_range( wield->value[1], wield->value[2] ); else proj_bonus = 0; } else { dt = TYPE_UNDEFINED; proj_bonus = 0; } /* * Can't beat a dead char! */ if( victim->position == POS_DEAD || victim->char_died( ) ) { projectile->extract( ); return rVICT_DIED; } if( wield ) prof_bonus = weapon_prof_bonus_check( ch, wield, prof_gsn ); else prof_bonus = 0; if( dt == TYPE_UNDEFINED ) { dt = TYPE_HIT; if( wield && wield->item_type == ITEM_MISSILE_WEAPON ) dt += wield->value[3]; } thac0 = calc_thac0( ch, victim, dist ); vic_ac = umax( -19, ( victim->GET_AC( ) / 10 ) ); /* * if you can't see what's coming... */ if( !victim->can_see_obj( projectile, false ) ) vic_ac += 1; if( !ch->can_see( victim, false ) ) vic_ac -= 4; /* * Weapon proficiency bonus */ vic_ac += prof_bonus; /* * The moment of excitement! */ while( ( diceroll = number_bits( 5 ) ) >= 20 ) ; if( diceroll == 0 || ( diceroll != 19 && diceroll < thac0 - vic_ac ) ) { /* * Miss. */ if( prof_gsn != -1 ) ch->learn_from_failure( prof_gsn ); /* * Do something with the projectile */ if( number_percent( ) < 50 ) projectile->extract( ); else { if( projectile->carried_by ) projectile->from_char( ); projectile->to_room( victim->in_room, victim ); } damage( ch, victim, 0, dt ); return rNONE; } /* * Hit. * Calc damage. */ pchance = number_range( 1, 10 ); switch ( pchance ) { case 1: case 2: case 3: /* Hit in the arm */ dam = number_range( projectile->value[1], projectile->value[2] ) + proj_bonus; break; case 4: case 5: case 6: /* Hit in the leg */ dam = number_range( ( 2 * projectile->value[1] ), ( 2 * projectile->value[2] ) ) + proj_bonus; break; default: case 7: case 8: case 9: case 10: /* Hit in the chest */ dam = number_range( ( 3 * projectile->value[1] ), ( 3 * projectile->value[2] ) ) + proj_bonus; break; } /* * Bonuses. */ dam += ch->GET_DAMROLL( ); if( prof_bonus ) dam += prof_bonus / 4; /* * Calculate Damage Modifiers from Victim's Fighting Style */ if( victim->position == POS_BERSERK ) dam = 1.2 * dam; else if( victim->position == POS_AGGRESSIVE ) dam = 1.1 * dam; else if( victim->position == POS_DEFENSIVE ) dam = .85 * dam; else if( victim->position == POS_EVASIVE ) dam = .8 * dam; if( !ch->isnpc( ) && ch->pcdata->learned[gsn_enhanced_damage] > 0 && number_percent( ) < ch->pcdata->learned[gsn_enhanced_damage] ) dam += ( int )( dam * ch->LEARNED( gsn_enhanced_damage ) / 120 ); else ch->learn_from_failure( gsn_enhanced_damage ); if( !victim->IS_AWAKE( ) ) dam *= 2; if( dam <= 0 ) dam = 1; plusris = 0; if( projectile->extra_flags.test( ITEM_MAGIC ) ) dam = ris_damage( victim, dam, RIS_MAGIC ); else dam = ris_damage( victim, dam, RIS_NONMAGIC ); /* * Handle PLUS1 - PLUS6 ris bits vs. weapon hitroll -Thoric */ if( wield ) plusris = wield->hitroll( ); /* * check for RIS_PLUSx - Thoric */ if( dam ) { int x, res, imm, sus, mod; if( plusris ) plusris = RIS_PLUS1 << UMIN( plusris, 7 ); /* * initialize values to handle a zero plusris */ imm = res = -1; sus = 1; /* * find high ris *//* * FIXME: Absorb handling needs to be included */ for( x = RIS_PLUS1; x <= RIS_PLUS6; ++x ) { if( victim->has_immune( x ) ) imm = x; if( victim->has_resist( x ) ) res = x; if( victim->has_suscep( x ) ) sus = x; } mod = 10; if( imm >= plusris ) mod -= 10; if( res >= plusris ) mod -= 2; if( sus <= plusris ) mod += 2; /* * check if immune */ if( mod <= 0 ) dam = -1; if( mod != 10 ) dam = ( dam * mod ) / 10; } /* * immune to damage */ if( dam == -1 ) { if( dt >= 0 && dt < num_skills ) { skill_type *skill = skill_table[dt]; bool found = false; if( skill->imm_char && skill->imm_char[0] != '\0' ) { act( AT_HIT, skill->imm_char, ch, nullptr, victim, TO_CHAR ); found = true; } if( skill->imm_vict && skill->imm_vict[0] != '\0' ) { act( AT_HITME, skill->imm_vict, ch, nullptr, victim, TO_VICT ); found = true; } if( skill->imm_room && skill->imm_room[0] != '\0' ) { act( AT_ACTION, skill->imm_room, ch, nullptr, victim, TO_NOTVICT ); found = true; } if( found ) { if( number_percent( ) < 50 ) projectile->extract( ); else { if( projectile->carried_by ) projectile->from_char( ); projectile->to_room( victim->in_room, victim ); } return rNONE; } } dam = 0; } if( ( retcode = damage( ch, victim, dam, dt ) ) != rNONE ) { if( projectile->value[5] == PROJ_STONE ) projectile->extract( ); else { if( victim->char_died( ) ) { projectile->extract( ); return rVICT_DIED; } projectile->from_char( ); projectile->to_char( victim ); projectile->extra_flags.set( ITEM_LODGED ); switch ( pchance ) { case 1: case 2: case 3: /* Hit in the arm */ projectile->wear_flags.set( ITEM_LODGE_ARM ); wear_obj( victim, projectile, true, get_wflag( "lodge_arm" ) ); break; case 4: case 5: case 6: /* Hit in the leg */ projectile->wear_flags.set( ITEM_LODGE_LEG ); wear_obj( victim, projectile, true, get_wflag( "lodge_leg" ) ); break; default: case 7: case 8: case 9: case 10: /* Hit in the chest */ projectile->wear_flags.set( ITEM_LODGE_RIB ); wear_obj( victim, projectile, true, get_wflag( "lodge_rib" ) ); break; } } return retcode; } if( ch->char_died( ) ) { projectile->extract( ); return rCHAR_DIED; } if( victim->char_died( ) ) { projectile->extract( ); return rVICT_DIED; } retcode = rNONE; if( dam == 0 ) { if( number_percent( ) < 50 ) projectile->extract( ); else { if( projectile->carried_by ) projectile->from_char( ); projectile->to_room( victim->in_room, victim ); } return retcode; } /* * weapon spells -Thoric */ if( wield && !victim->has_immune( RIS_MAGIC ) && !victim->in_room->flags.test( ROOM_NO_MAGIC ) ) { list < affect_data * >::iterator paf; for( paf = wield->pIndexData->affects.begin( ); paf != wield->pIndexData->affects.end( ); ++paf ) { affect_data *af = *paf; if( af->location == APPLY_WEAPONSPELL && IS_VALID_SN( af->modifier ) && skill_table[af->modifier]->spell_fun ) retcode = ( *skill_table[af->modifier]->spell_fun ) ( af->modifier, 7, ch, victim ); } if( retcode != rNONE || ch->char_died( ) || victim->char_died( ) ) { projectile->extract( ); return retcode; } for( paf = wield->affects.begin( ); paf != wield->affects.end( ); ++paf ) { affect_data *af = *paf; if( af->location == APPLY_WEAPONSPELL && IS_VALID_SN( af->modifier ) && skill_table[af->modifier]->spell_fun ) retcode = ( *skill_table[af->modifier]->spell_fun ) ( af->modifier, 7, ch, victim ); } if( retcode != rNONE || ch->char_died( ) || victim->char_died( ) ) { projectile->extract( ); return retcode; } } projectile->extract( ); return retcode; }