/*
 * 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;
}
Beispiel #2
0
void acid_effect(void *vo, int level, int dam, int target)
{
	if (target == TARGET_ROOM) /* nail objects on the floor */
	{
		ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo;
		OBJ_DATA *obj, *obj_next;

		for (obj = room->contents; obj != NULL; obj = obj_next)
		{
			obj_next = obj->next_content;
			acid_effect(obj,level,dam,TARGET_OBJ);
		}
		return;
	}

	if (target == TARGET_CHAR)  /* do the effect on a victim */
	{
		CHAR_DATA *victim = (CHAR_DATA *) vo;
		OBJ_DATA *obj, *obj_next;
		
	/* let's toast some gear */
		for (obj = victim->carrying; obj != NULL; obj = obj_next)
		{
			obj_next = obj->next_content;
			acid_effect(obj,level,dam,TARGET_OBJ);
		}
		return;
	}

	if (target == TARGET_OBJ) /* toast an object */
	{
		OBJ_DATA *obj = (OBJ_DATA *) vo;
		OBJ_DATA *t_obj,*n_obj;
		int chance = level / 4 + dam / 10;
		char *msg;

		if (IS_OBJ_STAT(obj,ITEM_BURN_PROOF)
			||  IS_OBJ_STAT(obj,ITEM_NOPURGE)
			||  number_range(0,4) == 0)
			return;

		if (chance > 25)
			chance = (chance - 25) / 2 + 25;
		if (chance > 50)
			chance = (chance - 50) / 2 + 50;

		if (IS_OBJ_STAT(obj,ITEM_BLESS))
			chance -= 5;

		chance -= obj->level * 2;

		switch (obj->item_type)
		{
			default:
			return;
			case ITEM_CONTAINER:
			case ITEM_CORPSE_PC:
			case ITEM_CORPSE_NPC:
			msg = "$p fumes and dissolves.";
			break;
			case ITEM_ARMOR:
			msg = "$p is pitted and etched.";
			break;
			case ITEM_CLOTHING:
			msg = "$p is corroded into scrap.";
			break;
			case ITEM_STAFF:
			case ITEM_WAND:
			chance -= 10;
			msg = "$p corrodes and breaks.";
			break;
			case ITEM_SCROLL:
			chance += 10;
			msg = "$p is burned into waste.";
			break; 
		}

		chance = URANGE(5,chance,95);

		if (number_percent() > chance)
			return;

		if (obj->carried_by != NULL)
			act(msg,obj->carried_by,obj,NULL,TO_ALL);
		else if (obj->in_room != NULL && obj->in_room->people != NULL)
			act(msg,obj->in_room->people,obj,NULL,TO_ALL);

	if (obj->item_type == ITEM_ARMOR)  /* etch it */
		{
			AFFECT_DATA *paf;
			bool af_found = FALSE;
			int i;

			affect_enchant(obj);

			for ( paf = obj->affected; paf != NULL; paf = paf->next)
			{
				if ( paf->location == APPLY_AC)
				{
					af_found = TRUE;
					paf->type = -1;
					paf->modifier += 1;
					paf->level = UMAX(paf->level,level);
					break;
				}
			}
			
			if (!af_found)
			/* needs a new affect */
			{
				paf = new_affect();
				
				paf->type       = -1;
				paf->level      = level;
				paf->duration   = -1;
				paf->location   = APPLY_AC;
				paf->modifier   =  1;
				paf->bitvector  = 0;
				paf->next       = obj->affected;
				obj->affected   = paf;
			}
			
			if (obj->carried_by != NULL && obj->wear_loc != WEAR_NONE)
				for (i = 0; i < 4; i++)
					obj->carried_by->armor[i] += 1;
				return;
			}

	/* get rid of the object */
	if (obj->contains)  /* dump contents */
			{
				for (t_obj = obj->contains; t_obj != NULL; t_obj = n_obj)
				{
					n_obj = t_obj->next_content;
					obj_from_obj(t_obj);
					if (obj->in_room != NULL)
						obj_to_room(t_obj,obj->in_room);
					else if (obj->carried_by != NULL)
						obj_to_room(t_obj,obj->carried_by->in_room);
					else
					{
						extract_obj(t_obj);
						continue;
					}

					acid_effect(t_obj,level/2,dam/2,TARGET_OBJ);
				}
			}

			extract_obj(obj);
			return;
		}
}
Beispiel #3
0
/* kwasowy efekt */
void acid_effect( void *vo, int level, int dam, int target )
{
    if ( target == TARGET_ROOM )
    {
        ROOM_INDEX_DATA * room = ( ROOM_INDEX_DATA * ) vo;
        OBJ_DATA *obj, *obj_next;

        for ( obj = room->contents; obj != NULL; obj = obj_next )
        {
            OBJ_NEXT_CONTENT( obj, obj_next );

            if ( IS_OBJ_STAT( obj, ITEM_NOPURGE ) )
                continue;

            acid_effect( obj, level, dam, TARGET_OBJ );
        }
        return ;
    }

    if ( target == TARGET_CHAR )   /* do the effect on a victim */
    {
        CHAR_DATA * victim = ( CHAR_DATA * ) vo;
        OBJ_DATA *obj, *obj_next;

        if ( !victim->in_room )
            return ;

		if ( is_affected(victim, gsn_mirrorfall) )
		{
			affect_strip(victim, gsn_mirrorfall);
			return;
		}

        /* brak sprawdzania czy zszedl */
        for ( obj = victim->carrying; obj != NULL; obj = obj_next )
        {
            OBJ_NEXT_CONTENT( obj, obj_next );
            acid_effect( obj, level, dam, TARGET_OBJ );
        }
        return ;
    }

    if ( target == TARGET_OBJ )  /* toast an object */
    {
        OBJ_DATA * obj = ( OBJ_DATA * ) vo;
        OBJ_DATA *t_obj, *n_obj;
        char *msg;

	/* Tener: dodanie szansy na unikniêcie w zale¿no¶ci od poziomu czaru [20080512] */
	//2008-11-20, Brohacz: wylaczam. Spelle powyzej 25 levela nie psuja przeciez przez to gratow!
	/*if ( URANGE( 1, number_range( 1, 30 - level ), 10 ) < 5 )
	   return;*/

        if ( !check_item_resist( obj, RESIST_ACID, dam ) )
            return ;

	if( obj->liczba_mnoga )
	{
	    switch ( obj->item_type )
            {
	        case ITEM_CONTAINER:
            	case ITEM_CORPSE_PC:
            	case ITEM_CORPSE_NPC:
	                msg = "$p sycz± i rozpuszczaj± siê.";
                	break;
            	case ITEM_ARMOR:
            	case ITEM_WEAPON:
	                msg = "$p skwiercz± i rozpadaj± siê.";
                	break;
            	case ITEM_CLOTHING:
	                msg = "$p czerniej± i krusz± siê.";
                	break;
            	case ITEM_STAFF:
            	case ITEM_WAND:
	                msg = "$p czerniej± i pêkaj±.";
                	break;
            	case ITEM_SCROLL:
	                msg = "$p rozpuszczaj± siê w k³ebach dymu.";
                	break;
            	default:
	                msg = "$p rozpuszczaj± siê w k³ebach dymu.";
                	break;
            }
        }
	else
	{
            switch ( obj->item_type )
            {
	        case ITEM_CONTAINER:
            	case ITEM_CORPSE_PC:
            	case ITEM_CORPSE_NPC:
	                msg = "$p syczy i rozpuszcza siê.";
                	break;
            	case ITEM_ARMOR:
            	case ITEM_WEAPON:
	                msg = "$p skwierczy i rozpada siê.";
                	break;
            	case ITEM_CLOTHING:
	                msg = "$p czernieje i kruszy siê.";
                	break;
            	case ITEM_STAFF:
            	case ITEM_WAND:
	                msg = "$p czernieje i pêka.";
                	break;
            	case ITEM_SCROLL:
	                msg = "$p rozpuszcza siê w k³ebach dymu.";
                	break;
            	default:
	                msg = "$p rozpuszcza siê w k³ebach dymu.";
                	break;
            }
        }



        if ( obj->carried_by != NULL )
            act( msg, obj->carried_by, obj, NULL, TO_ALL );
        else if ( obj->in_room != NULL && obj->in_room->people != NULL )
            act( msg, obj->in_room->people, obj, NULL, TO_ALL );

        /* get rid of the object */
        if ( obj->contains )   /* dump contents */
        {
            for ( t_obj = obj->contains; t_obj != NULL; t_obj = n_obj )
            {
                n_obj = t_obj->next_content;
                obj_from_obj( t_obj );

                if ( obj->in_room != NULL )
                    obj_to_room( t_obj, obj->in_room );

                else if ( obj->carried_by != NULL )
                    obj_to_room( t_obj, obj->carried_by->in_room );

                else
                {
                    /*artefact*/
                    if ( is_artefact( t_obj ) ) extract_artefact( t_obj );
                    if ( obj->contains ) extract_artefact_container( obj );
                    extract_obj( t_obj );
                    continue;
                }

                acid_effect( t_obj, level / 2, dam / 2, TARGET_OBJ );
            }
        }

        /*artefact*/
        if ( is_artefact( obj ) ) extract_artefact( obj );
        if ( obj->contains ) extract_artefact_container( obj );
        extract_obj( obj );
        return ;
    }
}