/
roa/
roa/lib/boards/
roa/lib/config/
roa/lib/edits/
roa/lib/help/
roa/lib/misc/
roa/lib/plrobjs/
roa/lib/quests/
roa/lib/socials/
roa/lib/www/
roa/lib/www/LEDSign/
roa/lib/www/LEDSign/fonts/
roa/lib/www/LEDSign/scripts/
roa/src/s_inc/
roa/src/sclient/
roa/src/sclient/binary/
roa/src/sclient/text/
roa/src/util/
/************************************************************************
	Realms of Aurealis 		James Rhone aka Vall of RoA

offensive.c				Routines of an offensive nature.
					Some assorted skills, but mostly
					generic offensive commands used
					to initiate battle.

		******** Heavily modified and expanded ********
		*** BE AWARE OF ALL RIGHTS AND RESERVATIONS ***
		******** Heavily modified and expanded ********
		        All rights reserved henceforth. 

    Please note that no guarantees are associated with any code from
Realms of Aurealis.  All code which has been released to the general
public has been done so with an 'as is' pretense.  RoA is based on both
Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well
as the RoA license.   *** Read, Learn, Understand, Improve ***
*************************************************************************/
#include "conf.h"
#include "sysdep.h"

#include "structures.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "acmd.h"
#include "handler.h"
#include "db.h"
#include "magic.h"
#include "mudlimits.h"
#include "fight.h"
#include "lists.h"
#include "global.h"

/* extern functions */
int	do_simple_move(chdata *ch, int cmd, int following);

ACMD(do_assist)
{
  chdata *helpee, *opp;

  if (IN_NOWHERE(ch)) return;

  if (FIGHTING(ch)) 
  {
    send_to_char("You're already fighting!\n\r", ch);
    return;
  }

  one_argument(argument, arg);

  if (!*arg)
  {
    send_to_char("Assist whom?\n\r",ch);
    return;
  }

  if (!(helpee = get_char_room_vis(ch, arg)))
  {
    send_to_char("Assist whom?\n\r", ch);
    return;
  }

  if (helpee == ch)
  {
    send_to_char("You can't help yourself any more than this!\n\r", ch);
    return;
  }

  for(opp = world[ch->in_room].people; opp && (FIGHTING(opp) != helpee); 
      opp = opp->next_in_room)
    ;

  if (!opp)
  {
    act("But nobody is fighting $M!", FALSE, ch, 0, helpee, TO_CHAR);
    return;
  }

  if (!can_see(ch, opp))
  {
    act("You can't see who's fighting $M!", FALSE, ch, 0, helpee, TO_CHAR);
    return;
  }

  if (!check_truce(ch, opp))
    return;
  if (!check_mortal_combat(ch, opp))
    return;

  send_to_char("%BYou join the fight%0!\n\r", ch);
  act("$N assists you!", TRUE, helpee, 0, ch, TO_CHAR);
  act("$n assists $N.", TRUE, ch, 0, helpee, TO_NOTVICT);

  // have to set fighting here... might return prematurely from hit()
  if (!(FIGHTING(ch)))
    set_fighting(ch, opp);

  hit(ch, opp, TYPE_UNDEFINED, TRUE);
}

ACMD(do_hit)
{
  chdata *victim;
  extern void start_cityguard_hunt(chdata *ch);

  if (IN_NOWHERE(ch)) return;

  if (IS_IMMORTAL(ch) && GET_LEVEL(ch) < LEV_AIMP)
  {
     send_to_char("You, being an Immortal, are forbidden to kill.\n\r",ch);
     return;
  }

  if (GET_LEVEL(ch) < LEV_AIMP && ROOM_FLAGGED(ch->in_room, PEACEFUL))
  {
    send_to_char("Your offensive actions lead to naught in this peaceful area.\n\r",ch);
    return;
  }

  one_argument(argument, arg);

  if (!*arg)
  {
    send_to_char("Hit who?\n\r",ch);
    return;
  }

  switch (GET_POS(ch)) {
    case POS_MOUNTED:
      send_to_char("You must dismount first!\n\r",ch);
      return;

    case POS_FLOATING:
      send_to_char("You cannot fight while in flight.\n\r",ch);
      return;

    case POS_FIGHTING:
      send_to_char("You %Bare%0 fighting!\n\r",ch);
      return;

    default:
      break;
  };
  
  if (!(victim = get_char_room_vis(ch, arg))) 
  {
    send_to_char("They aren't here.\n\r",ch);
    return; 
  }

  if (victim == ch) 
  {
    send_to_char("You hit yourself...OUCH!.\n\r", ch);
    act("$n hits $mself, doh!", FALSE, ch, 0, 0, TO_ROOM);
    return;
  }

  if (IS_PC(victim) && IS_PC(ch) && !IN_ARENA(ch) && !IN_ARENA(victim)) 
  {
    if (subcmd == SCMD_MURDER) 
    {
      if (IS_ASSASSIN(ch) && IS_ASSASSIN(victim)) 
	act("You attempt to assassinate $N.", TRUE, ch, 0, victim, TO_CHAR);
      else 
      {
        send_to_char("Only Assassins may fight other Assassins.\n\r\n\r",ch);
        send_to_char("To learn more, %Bhelp assassin%0.\n\r",ch); 
	return;
      }
    } 
    else 
    { /* not murder command */
      send_to_char("You must type %BMURDER%0 to kill another player.\n\r",ch);
      return;
    }
  }

  if (CHARMED(ch) && ch->master && IS_PC(ch->master) && IS_PC(victim))
    return; /* you can't order a charmed pet to attack a player */

  if (CHARMED(ch) && (ch->master == victim)) {
    act("You find yourself unable to hit $N.", FALSE, ch, 0, victim, TO_CHAR);
    return;
  }

  if ((GET_POS(ch) == POS_STANDING) && (victim != FIGHTING(ch)) && 
      check_truce(ch, victim))
  {
    if (SPC_FLAGGED(victim, SPC_CITYGUARD) && !number(0, 1))  
      start_cityguard_hunt(ch);
 
    hit(ch, victim, TYPE_UNDEFINED, TRUE);
    WAIT_STATE(ch, PULSE_VIOLENCE); 
  }
}

ACMD(do_kill)
{
  chdata *victim;

  if (IN_NOWHERE(ch)) return;

  if (IS_IMMORTAL(ch) && GET_LEVEL(ch) < LEV_AIMP)
  {
     send_to_char("You, being an Immortal, are forbidden to kill.\n\r",ch);
     return;
  }
  
  if (GET_LEVEL(ch) < LEV_AIMP && ROOM_FLAGGED(ch->in_room, PEACEFUL))
  {
    send_to_char("Your offensive actions lead to naught in this peaceful area.\n\r",ch);
    return;
  }

  /* normal killin gets sent to do_hit from here */
  if ((GET_LEVEL(ch) < LEV_IMPL) || IS_NPC(ch)) {
     do_hit(ch, argument, cmd, subcmd);
     return;
  }

  one_argument(argument, arg);

  if (!*arg) 
  {
    send_to_char("Kill who?\n\r", ch);
    return;
  }

  if (!(victim = get_char_room_vis(ch, arg)))
  {
    send_to_char("They aren't here.\n\r", ch);
    return;
  }

  if (ch == victim)
  {
    send_to_char("There are clinics for that type of thing... :(\n\r", ch);
    return;
  }

  act("You chop $M to pieces!  Ah!  The blood!", FALSE, ch, 0, victim, TO_CHAR);
  act("$N chops you to pieces!", TRUE, victim, 0, ch, TO_CHAR);
  act("$n brutally slays $N!", TRUE, ch, 0, victim, TO_NOTVICT);
  raw_kill(victim);
}

ACMD(do_order)
{
  char	name[512], message[512];
  BOOL found = FALSE;
  chdata *victim;
  struct follow_type *k;

  if (strlen(argument) > 1000)
  {
    send_to_char("Argument length too long.  Your actions have been logged.\n\r",ch);
    sprintf(buf, "PLRUPD: Excessive argument length to do_order (%s).", GET_NAME(ch));
    mudlog(buf, BRF, LEV_IMM, TRUE);
    return;
  }

  half_chop(argument, name, message);

  if (!*name || !*message)
  {
    send_to_char("Order who to do what?\n\r", ch);
    return;
  }

  if (!(victim = get_char_room_vis(ch, name)) && !is_abbrev(name, "followers"))
  {
    send_to_char("That person isn't here.\n\r", ch);
    return;
  }

  if (ch == victim)
  {
    send_to_char("You obviously suffer from skitzofrenia.\n\r", ch);
    return;
  }

  if (CHARMED(ch))
  {
    send_to_char("Your superior would not approve of you giving orders.\n\r", ch);
    return;
  }

  if (victim) 
  {
    sprintf(buf, "$N orders you to '%s'", message);
    act(buf, FALSE, victim, 0, ch, TO_CHAR);
    act("$n gives $N an order.", FALSE, ch, 0, victim, TO_ROOM);

    if (victim->master != ch || !CHARMED(victim))
      act("$n has an indifferent look.", FALSE, victim, 0, 0, TO_ROOM);
    else 
    {
      send_to_char("Ok.\n\r", ch);
      command_interpreter(victim, message);
    }
  } 
  else  // must have ordered followers
  {
    sprintf(buf, "$n issues the order '%s'.", message);
    act(buf, FALSE, ch, 0, 0, TO_ROOM);

    for (k = ch->followers; k; k = k->next) 
      if (SAME_ROOM(ch, k->follower) && CHARMED(k->follower)) 
      {
        found = TRUE;
        command_interpreter(k->follower, message);
      }

    if (found)
      send_to_char("Ok.\n\r", ch);
    else
      send_to_char("Nobody here is a loyal subject of yours!\n\r", ch);
  }
}

#define NUM_FLEE_CHANCES   6

ACMD(do_flee)
{
  int	i, attempt, lose, die;
  int	gain_exp(chdata *ch, int gain);
  int	special(chdata *ch, int cmd, char *arg);
  chdata *enemy = 0;

  if (IS_NPC(ch) && (GET_POS(ch) == POS_SITTING)) 
  {
    send_to_char("Stand up bozo! \n\r", ch);
    do_stand(ch, "", 0, 0);
    GET_POS(ch) = POS_FIGHTING;
    return;
  }

  if (!(FIGHTING(ch))) 
  {
    for (i = 1; i < NUM_FLEE_CHANCES; i++) 
    {
      attempt = number(0, NUM_OF_DIRS-1);  /* Select a random direction */
      if (CAN_GO(ch, attempt) && 
	  !ROOM_FLAGGED(EXIT(ch, attempt)->to_room, DEATH) && 
	  !ROOM_FLAGGED(EXIT(ch, attempt)->to_room, FLY_DEATH)) 
      {
	act("$n panics, and attempts to flee!", TRUE, ch, 0, 0, TO_ROOM);
	if ((die = do_simple_move(ch, attempt, FALSE)) == TRUE) // success!
	  send_to_char("You flee head over heels.\n\r", ch);
	else 
	{
	  if (!die)
	    act("$n tries to flee, but is too exhausted!", TRUE, ch, 0, 0, TO_ROOM);
	}
	return;
      }
    } 
    send_to_char("%BPANIC!%0  You couldn't escape!\n\r", ch);
    return;
  }

  for (i = 0; i < NUM_FLEE_CHANCES - 1; i++) 
  {
    attempt = number(0, NUM_OF_DIRS-1);  /* Select a random direction */
    if (CAN_GO(ch, attempt) && 
        !ROOM_FLAGGED(EXIT(ch, attempt)->to_room, DEATH) &&
        !ROOM_FLAGGED(EXIT(ch, attempt)->to_room, FLY_DEATH)) 
    {
      act("$n panics, and attempts to flee!", TRUE, ch, 0, 0, TO_ROOM);

      /* if the move succeeds, i.e. not death and dir */
      if ((die = do_simple_move(ch, attempt, FALSE)) == TRUE) 
      {
        lose = GET_MAX_HIT(FIGHTING(ch)) - GET_HIT(FIGHTING(ch));
        lose *= GET_LEVEL(FIGHTING(ch));
        lose = MIN(lose, maxfleeexploss);  /* max loss cause of fleeing 200k*/

        // if thief, lose less per flee...
        if (IS_THIEF(ch))
         lose /= 2;

	if (IS_PC(ch) && !IN_ARENA(ch))
	  gain_exp(ch, -lose);
	send_to_char("You flee head over heels.\n\r", ch);

	enemy = FIGHTING(ch);
	HUNTING(enemy) = ch;

	/* before we stop fighting, make sure combat was disengaged */
	if (IS_PC(enemy) && GET_SKILL(enemy, SKILL_FENGAGE) > number(5, 110) &&
            !CHAR_FLAGGED(enemy, CH_SUBDUED))
	{
	  /* move enemy with ch, do not disengage -roa */
	  do_simple_move(enemy, attempt, FALSE);
	  act("You follow $N!",TRUE,enemy,0,ch,TO_CHAR);
	  act("$n follows you!",TRUE,enemy,0,ch,TO_VICT);
	  act("$n follows $N!",TRUE,enemy,0,ch,TO_ROOM);
	  return;
	}

	/* ok, it was disengaged properly, stop the fight */
	if (FIGHTING(enemy) == ch)
	  stop_fighting(enemy);
	stop_fighting(ch);
	return;
      } 
      else 
      {
	if (!die)
	  act("$n tries to flee, but cannot!", TRUE, ch, 0, 0, TO_ROOM);
	return;
      }
    }
  } 
  send_to_char("%BPANIC!!!%0  You couldn't escape!\n\r", ch);
}