Kicking

From IvanWiki
Revision as of 02:08, 1 September 2014 by 4zb4 (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Coding: This article contains code which is for experienced users only, and may reveal game secrets

Spoiler Warning: This page contains spoilers which may affect your IVAN experience negatively

//work in progress
Kicking with (k) allows the player to apply the full force of his legs upon an adjacent tile and anything that happens to be occupying it at the time.

The effect of being kicked depends on what type of entity is on the receiving end. Enemies will make a hit check for damage and being thrown off balance, items will be thrown a certain distance, and walls or other terrain objects will check for damage.

void character::BeKicked(character* Kicker, item* Boot, bodypart* Leg, v2 HitPos, double KickDamage, double ToHitValue, int Success, int Direction, truth Critical, truth ForceHit)
{
  switch(TakeHit(Kicker, Boot, Leg, HitPos, KickDamage, ToHitValue, Success, KICK_ATTACK, Direction, Critical, ForceHit))
  {
   case HAS_HIT:
   case HAS_BLOCKED:
   case DID_NO_DAMAGE:
    if(IsEnabled() && !CheckBalance(KickDamage))
    {
      if(IsPlayer())
	ADD_MESSAGE("The kick throws you off balance.");
      else if(Kicker->IsPlayer())
	ADD_MESSAGE("The kick throws %s off balance.", CHAR_DESCRIPTION(DEFINITE));

      v2 FallToPos = GetPos() + game::GetMoveVector(Direction);
      FallTo(Kicker, FallToPos);
    }
  }
}

A kick's damage is determined by the boot on the foot used, the user's base kick strength (default is double the user's unarmed strength), the user's LSTR and the user's kicking skill.

void leg::CalculateDamage()
{
  if(!Master)
    return;

  double WeaponStrength = GetBaseKickStrength() * GetBaseKickStrength();
  item* Boot = GetBoot();

  if(Boot)
    WeaponStrength += Boot->GetWeaponStrength();

  double Base = sqrt(5e-5 * WeaponStrength);

  if(Boot)
    Base += Boot->GetDamageBonus();

  KickDamage = Base * sqrt(1e-7 * GetAttribute(LEG_STRENGTH))
	       * GetHumanoidMaster()->GetCWeaponSkill(KICK)->GetBonus();
}

A kick's to-hit value is calculated using the equipped boot's to-hit bonus and the user's AGI, PER, kicking skill and burden value.

void leg::CalculateToHitValue()
{
  if(!Master)
    return;

  double BonusMultiplier = 10.;
  item* Boot = GetBoot();

  if(Boot)
    BonusMultiplier += Boot->GetTHVBonus();

  KickToHitValue = GetAttribute(AGILITY)
		   * sqrt(2.5 * Master->GetAttribute(PERCEPTION))
		   * GetHumanoidMaster()->GetCWeaponSkill(KICK)->GetBonus()
		   * Master->GetMoveEase()
		   * BonusMultiplier / 10000000;
}

Enemies

Enemies that are kicked can both be damaged by it and be thrown backward a single tile. A kick's hit value is calculated in the same way as a normal hit, using the same takeHit(...) function as in normal combat.
In order to be launched by a kick, the enemy must fail a balance check. Firstly, the enemy must be able to move and cannot be flying. Secondly, a check is made against the KickDamage found above versus the remainder found after dividing the enemy's size by a randomly generated number.

If this check is failed, the enemy will be thrown back a single tile. However, if a wall is in the way the enemy will crash into it with its head and take damage. If another entity is in the way of the kicked enemy, it will either swap places with it (due to the monster charging forward to occupy the tile next to the player) or fail to be moved at all.

truth character::CheckBalance(double KickDamage)
{
  return !CanMove()
    || IsStuck()
    || !KickDamage
    || (!IsFlying()
	&& KickDamage * 5 < RAND() % GetSize());
}

The damage done by being kicked into a wall is equivalent to the remainder of (1 + a random number) / 5 and is applied directly to the head.

if(NoRoom)
    {
      if(HasHead())
      {
	if(IsPlayer())
	  ADD_MESSAGE("You hit your head on the wall.");
	else if(CanBeSeenByPlayer())
	  ADD_MESSAGE("%s hits %s head on the wall.", CHAR_NAME(DEFINITE), GetPossessivePronoun().CStr());
      }

      ReceiveDamage(GuiltyGuy, 1 + RAND() % 5, PHYSICAL_DAMAGE, HEAD);
      CheckDeath(CONST_S("killed by hitting a wall due to being kicked @bk"), GuiltyGuy);
    }