/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
#include <glib.h>
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <merc.h>
#include <tables.h>
#include <interp.h>
#include <fight.h>
void set_attack_flag(CHAR_DATA *ch, CHAR_DATA *victim)
{
if ( ch == victim )
return;
if (ch == NULL || victim == NULL)
return;
if (IS_NPC(ch) || IS_NPC(victim))
return;
/* Attack Flag Check */
if (!CAN_PK(ch) || !CAN_PK(victim))
return;
if (IS_SABBAT(victim))
{
ch->attack_timer = 8;
if (!IS_SET(ch->act, PLR_ATTACK))
SET_BIT(ch->act, PLR_ATTACK);
if (!IS_SET(ch->pk_sect, ATTACK_SABBAT))
SET_BIT(ch->pk_sect, ATTACK_SABBAT);
}
else if (IS_FOLLOWERS(victim))
{
ch->attack_timer = 8;
if (!IS_SET(ch->act, PLR_ATTACK))
SET_BIT(ch->act, PLR_ATTACK);
if (!IS_SET(ch->pk_sect, ATTACK_SABBAT))
SET_BIT(ch->pk_sect, ATTACK_FOLLOWERS);
}
else if (IS_CAMARILLA(victim))
{
ch->attack_timer = 8;
if (!IS_SET(ch->act, PLR_ATTACK))
SET_BIT(ch->act, PLR_ATTACK);
if (!IS_SET(ch->pk_sect, ATTACK_CAMARILLA))
SET_BIT(ch->pk_sect, ATTACK_CAMARILLA);
}
else if (IS_WYRM(victim))
{
ch->attack_timer = 8;
if (!IS_SET(ch->act, PLR_ATTACK))
SET_BIT(ch->act, PLR_ATTACK);
if (!IS_SET(ch->pk_sect, ATTACK_WYRM))
SET_BIT(ch->pk_sect, ATTACK_WYRM);
}
else if (IS_PACK(victim))
{
ch->attack_timer = 8;
if (!IS_SET(ch->act, PLR_ATTACK))
SET_BIT(ch->act, PLR_ATTACK);
if (!IS_SET(ch->pk_sect, ATTACK_PACK))
SET_BIT(ch->pk_sect, ATTACK_PACK);
}
else if (IS_CLASS(victim,CLASS_VAMPIRE))
{
ch->attack_timer = 8;
if (!IS_SET(ch->act, PLR_ATTACK))
SET_BIT(ch->act, PLR_ATTACK);
if (!IS_SET(ch->pk_sect, ATTACK_VAMP))
SET_BIT(ch->pk_sect, ATTACK_VAMP);
}
else if (IS_CLASS(victim,CLASS_MAGE))
{
ch->attack_timer = 8;
if (!IS_SET(ch->act, PLR_ATTACK))
SET_BIT(ch->act, PLR_ATTACK);
if (!IS_SET(ch->pk_sect, ATTACK_MAGE))
SET_BIT(ch->pk_sect, ATTACK_MAGE);
}
else if (IS_SWWF(victim))
{
ch->attack_timer = 8;
if (!IS_SET(ch->act, PLR_ATTACK))
SET_BIT(ch->act, PLR_ATTACK);
if (!IS_SET(ch->pk_sect, ATTACK_WWF))
SET_BIT(ch->pk_sect, ATTACK_WWF);
}
return;
}
bool check_pk_range(CHAR_DATA *ch, CHAR_DATA *victim)
{
int chclass,victimclass;
if (ch->race <= 0 ) chclass = 0;
else if (ch->race <= 4 ) chclass = 1;
else if (ch->race <= 9 ) chclass = 2;
else if (ch->race <= 14) chclass = 3;
else if (ch->race <= 19) chclass = 4;
else if (ch->race <= 24) chclass = 5;
else chclass = 6;
if (victim->race <= 0 ) victimclass = 0;
else if (victim->race <= 4 ) victimclass = 1;
else if (victim->race <= 9 ) victimclass = 2;
else if (victim->race <= 14) victimclass = 3;
else if (victim->race <= 19) victimclass = 4;
else if (victim->race <= 24) victimclass = 5;
else victimclass = 6;
if ( chclass > victimclass )
return TRUE;
else
return FALSE;
}
bool check_pk(CHAR_DATA *ch, CHAR_DATA *victim,int flag)
{
/* Universal Check all by Spiralsoft(tm) <g> */
bool pksect = FALSE;
bool canpk = FALSE;
if ( ch == NULL || victim == NULL)
return FALSE;
if (IS_NPC(victim) || IS_NPC(ch))
return FALSE;
if (!CAN_PK(ch) || !CAN_PK(victim))
return TRUE;
if (IS_SET(flag,CHECK_DELAY))
{
if (HAS_DELAY(ch) || HAS_DELAY(victim))
{
if (IS_NPC(victim))
{
bug("Damn mobs.",0);
return FALSE;
}
send_to_char("You or your victim has a delay timer, please wait to attack (type 'help wait' for more info.)\n\r",ch);
return TRUE;
}
}
if (IS_ITEMAFF(victim, ITEMA_ARTIFACT)){
return FALSE;
}
canpk = check_pk_range(ch,victim);
if (IS_SET(flag,CHECK_ATTACK))
{
/* Check for attack flag */
if ( canpk && !IS_SET(victim->act,PLR_ATTACK))
{
send_to_char("Go pick on someone else.\n\r",ch);
return TRUE;
}
if (IS_SET(victim->act,PLR_ATTACK) && canpk )
{
/* Check for Sect, this is done by bit */
if (IS_SET(victim->pk_sect,ATTACK_SABBAT) && !IS_SABBAT(ch))
pksect = TRUE;
if (IS_SET(victim->pk_sect,ATTACK_FOLLOWERS) && !IS_FOLLOWERS(ch))
pksect = TRUE;
if (IS_SET(victim->pk_sect,ATTACK_CAMARILLA) && !IS_CAMARILLA(ch))
pksect = TRUE;
if (IS_SET(victim->pk_sect,ATTACK_WYRM) && !IS_WYRM(ch))
pksect = TRUE;
if (IS_SET(victim->pk_sect,ATTACK_PACK) && !IS_PACK(ch))
pksect = TRUE;
if (IS_SET(victim->pk_sect,ATTACK_VAMP) && !IS_CLASS(ch,CLASS_VAMPIRE))
pksect = TRUE;
if (IS_SET(victim->pk_sect,ATTACK_WWF) && !IS_CLASS(ch,CLASS_WEREWOLF))
pksect = TRUE;
if (IS_SET(victim->pk_sect,ATTACK_MAGE) && !IS_CLASS(ch,CLASS_MAGE))
pksect = TRUE;
if (IS_SET(victim->pk_sect,ATTACK_ANYONE))
pksect = TRUE;
if (pksect == TRUE)
{
send_to_char("They did nothing to you or your sect, you can't attack them.\n\r",ch);
return TRUE;
}
}
}
return FALSE;
}
bool check_safe_imm(CHAR_DATA *ch)
{
CHAR_DATA *wch;
for (wch = char_list; wch != NULL; wch = wch->next)
{
if (wch->in_room == NULL)
continue;
if (!IS_NPC(wch) && wch->in_room == ch->in_room
&& IS_IMMORTAL(wch) && IS_SET(wch->pcdata->comm, COMM_IMM_SAFE))
return TRUE;
}
return FALSE;
}
bool is_tempsafe( CHAR_DATA *ch )
{
if ( ch->fighting == NULL && ch->in_room != NULL && IS_SET(ch->in_room->room_flags,ROOM_SAFE) )
{
switch (weather_info[ch->in_room->sector_type].sunlight)
{
case SUN_DARK:
return FALSE;
case SUN_LIGHT:
case SUN_SET:
case SUN_RISE:
return TRUE;
}
}
return FALSE;
}
bool is_safe( CHAR_DATA *ch, CHAR_DATA *victim )
{
/* Ethereal people can only attack other ethereal people */
if (ch->plane != victim->plane){
send_to_char("They are not on this plane.\n\r",ch);
return TRUE;
}
if ( ch->in_room != NULL && IS_SET(ch->in_room->room_flags,ROOM_SAFE) && victim->pk_timer < 1)
{
switch (weather_info[ch->in_room->sector_type].sunlight)
{
case SUN_DARK:
break;
case SUN_LIGHT:
case SUN_SET:
case SUN_RISE:
send_to_char( "You cannot fight in a safe room during the daytime.\n\r", ch );
return TRUE;
}
}
if ( IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH) )
{
send_to_char( "Objects cannot fight!\n\r", ch );
return TRUE;
}
else if ( IS_HEAD(victim,LOST_HEAD) || IS_EXTRA(victim,EXTRA_OSWITCH))
{
send_to_char( "You cannot attack an object.\n\r", ch );
return TRUE;
}
if ( IS_NPC(ch) || IS_NPC(victim) )
return FALSE;
/* Thx Josh! */
if ( victim->fighting == ch )
return FALSE;
if (IS_ITEMAFF(ch, ITEMA_PEACE))
{
send_to_char( "You are unable to attack them.\n\r", ch );
return TRUE;
}
switch(ch->plane)
{
case PLANE_SPIRIT:
return TRUE;
case PLANE_PUNISHMENT:
return TRUE;
case PLANE_IMMORTAL:
return TRUE;
}
if (IS_ITEMAFF(victim, ITEMA_PEACE))
{
send_to_char( "You can't seem to attack them.\n\r", ch );
return TRUE;
}
if ( check_pk(ch,victim,CHECK_DELAY))
{
return TRUE;
}
if ( ch->trust > LEVEL_BUILDER )
{
send_to_char( "You cannot fight if you have implementor powers!\n\r", ch );
return TRUE;
}
if ( victim->trust > LEVEL_BUILDER )
{
send_to_char( "You cannot fight someone with implementor powers!\n\r", ch );
return TRUE;
}
if ( !CAN_PK(ch) || !CAN_PK(victim) )
{
send_to_char( "Both players must be avatars to fight.\n\r", ch );
return TRUE;
}
if ( ch->desc == NULL || ( victim->desc == NULL && victim->pk_timer < 1 ))
{
if (victim->position != POS_FIGHTING)
{
send_to_char( "They are currently link dead with no combat timer.\n\r", ch );
send_to_char( "Are you that much of a pussy that you have to kill link dead?\n\r", ch );
return TRUE;
}
}
return FALSE;
}
bool no_attack( CHAR_DATA *ch, CHAR_DATA *victim )
{
/* Ethereal people can only attack other ethereal people */
if (ch->plane != victim->plane){
send_to_char("They are not on this plane.\n\r",ch);
return TRUE;
}
if ( ch->in_room != NULL && is_safe(ch,victim) )
{
send_to_char( "You cannot fight in a safe room.\n\r", ch );
return TRUE;
}
if ( IS_HEAD(ch,LOST_HEAD) || IS_EXTRA(ch,EXTRA_OSWITCH) )
{
send_to_char( "Objects cannot fight!\n\r", ch );
return TRUE;
}
else if ( IS_HEAD(victim,LOST_HEAD) || IS_EXTRA(victim,EXTRA_OSWITCH) )
{
send_to_char( "You cannot attack objects.\n\r", ch );
return TRUE;
}
return FALSE;
}
/*
* See if an attack justifies a KILLER flag.
*/
void check_killer( CHAR_DATA *ch, CHAR_DATA *victim )
{
/*
* Follow charm thread to responsible character.
* Attacking someone's charmed char is hostile!
*/
while ( IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL )
victim = victim->master;
/*
* NPC's are fair game.
* So are killers and thieves.
*/
if ( IS_NPC(victim) )
return;
/*
* Charm-o-rama.
*/
if ( IS_SET(ch->affected_by, AFF_CHARM) )
{
if ( ch->master == NULL )
{
affect_strip( ch, gsn_charm_person );
REMOVE_BIT( ch->affected_by, AFF_CHARM );
return;
}
stop_follower( ch );
return;
}
return;
}
void calc_stat(CHAR_DATA *ch, CHAR_DATA *victim)
{
/* Check for attack flag */
if ( victim->race >= ch->race && victim->race > 0 )
{
ch->race++;
victim->race--;
}
ch->pkill++;
victim->pdeath++;
}