forked from Mirrors/openclonk
Move bomber and club attackers from FightForGidl to default AI as attack modes
parent
f754210a99
commit
649d7bed0a
|
@ -29,23 +29,10 @@ public func FindTarget(effect fx)
|
|||
return target;
|
||||
}
|
||||
|
||||
private func FindInventoryWeapon(effect fx)
|
||||
private func CheckVehicleAmmo(effect fx, object catapult)
|
||||
{
|
||||
// Extra weapons
|
||||
if (fx.weapon = fx.Target->FindContents(PowderKeg))
|
||||
{
|
||||
fx.strategy = this.ExecuteBomber;
|
||||
return true;
|
||||
}
|
||||
if (fx.weapon = fx.Target->FindContents(Club))
|
||||
{
|
||||
fx.strategy = this.ExecuteClub;
|
||||
return true;
|
||||
}
|
||||
if (inherited(fx, ...))
|
||||
return true;
|
||||
// no weapon :(
|
||||
return false;
|
||||
// Ammo is auto-refilled
|
||||
return true;
|
||||
}
|
||||
|
||||
private func ExecuteBomber(effect fx)
|
||||
|
@ -72,55 +59,6 @@ private func ExecuteBomber(effect fx)
|
|||
return true;
|
||||
}
|
||||
|
||||
private func ExecuteClub(effect fx)
|
||||
{
|
||||
// Still carrying the melee weapon?
|
||||
if (fx.weapon->Contained() != fx.Target)
|
||||
{
|
||||
fx.weapon = nil;
|
||||
return false;
|
||||
}
|
||||
// Are we in range?
|
||||
var x=fx.Target->GetX(), y=fx.Target->GetY(), tx=fx.target->GetX(), ty=fx.target->GetY();
|
||||
var dx = tx-x, dy = ty-y;
|
||||
if (Abs(dx) <= 10 && PathFree(x,y,tx,ty))
|
||||
{
|
||||
if (Abs(dy) >= 15)
|
||||
{
|
||||
// Clonk is above or below us - wait
|
||||
if (dx<-5) fx.Target->SetComDir(COMD_Left); else if (dx>5) fx.Target->SetComDir(COMD_Right); else fx.Target->SetComDir(COMD_None);
|
||||
return true;
|
||||
}
|
||||
if (!this->CheckHandsAction(fx)) return true;
|
||||
// Stop here
|
||||
fx.Target->SetCommand("None"); fx.Target->SetComDir(COMD_None);
|
||||
// cooldown?
|
||||
if (!fx.weapon->CanStrikeWithWeapon(fx.Target))
|
||||
{
|
||||
//Message("MeleeWAIT %s @ %s!!!", fx.weapon->GetName(), fx.target->GetName());
|
||||
// While waiting for the cooldown, we try to evade...
|
||||
ExecuteEvade(fx,dx,dy);
|
||||
return true;
|
||||
}
|
||||
// OK, attack! Prefer upwards strike
|
||||
dy -= 16;
|
||||
fx.weapon->ControlUseStart(fx.Target, dx,dy);
|
||||
fx.weapon->ControlUseHolding(fx.Target, dx,dy);
|
||||
fx.weapon->ControlUseStop(fx.Target, dx,dy);
|
||||
return true;
|
||||
}
|
||||
// Not in range. Walk there.
|
||||
if (!fx.Target->GetCommand() || !Random(10)) fx.Target->SetCommand("MoveTo", fx.target);
|
||||
//Message("Melee %s @ %s!!!", fx.weapon->GetName(), fx.target->GetName());
|
||||
return true;
|
||||
}
|
||||
|
||||
private func CheckVehicleAmmo(effect fx, object catapult)
|
||||
{
|
||||
// Ammo is auto-refilled
|
||||
return true;
|
||||
}
|
||||
|
||||
func Execute(effect fx, int time)
|
||||
{
|
||||
// Execution: No defensive AI. All enemies move towards target
|
||||
|
|
|
@ -32,7 +32,12 @@ local AttackModes = {}; // empty pre-init to force proplist ownership in base AI
|
|||
local SingleWeaponAttackMode = {
|
||||
Construction = func(effect fx)
|
||||
{
|
||||
// Contents hack: Carry heavy collection while "Walk" plays an annoying animation. Skip that by having a jump animation
|
||||
// (the jump animation skipping pickup is weird anyway, but it works for now)
|
||||
var is_carry_heavy_workaround = fx.attack_mode.Weapon->~IsCarryHeavy() && !fx.Target->Contained() && fx.Target->GetAction() == "Walk";
|
||||
if (is_carry_heavy_workaround) fx.Target->SetAction("Jump");
|
||||
var weapon = fx.Target->CreateContents(fx.attack_mode.Weapon);
|
||||
if (is_carry_heavy_workaround) fx.Target->SetAction("Walk");
|
||||
if (weapon)
|
||||
{
|
||||
if (fx.attack_mode.Ammo)
|
||||
|
@ -130,8 +135,9 @@ private func DefinitionAttackModes(proplist def)
|
|||
// Register presets for all the default weapons usable by the AI
|
||||
def->RegisterAttackMode("Default", { Name = "$Default$", EditorHelp = "$DefaultHelp$", FindWeapon = AI.FindInventoryWeapon });
|
||||
def->RegisterAttackMode("Sword", new SingleWeaponAttackMode { Weapon = Sword, Strategy = this.ExecuteMelee });
|
||||
def->RegisterAttackMode("Club", new SingleWeaponAttackMode { Weapon = Club, Strategy = this.ExecuteMelee });
|
||||
def->RegisterAttackMode("Axe", new SingleWeaponAttackMode { Weapon = Axe, Strategy = this.ExecuteMelee });
|
||||
def->RegisterAttackMode("Club", new SingleWeaponAttackMode { Weapon = Club, Strategy = this.ExecuteClub });
|
||||
def->RegisterAttackMode("PowderKeg", new SingleWeaponAttackMode { Weapon = PowderKeg, Strategy = this.ExecuteBomber });
|
||||
def->RegisterAttackMode("BowArrow", new SingleWeaponAttackMode { Weapon = Bow, Ammo = Arrow, FindWeapon = this.FindInventoryWeaponBow });
|
||||
def->RegisterAttackMode("BowFireArrow", new SingleWeaponAttackMode { Weapon = Bow, Ammo = FireArrow, FindWeapon = this.FindInventoryWeaponBow });
|
||||
def->RegisterAttackMode("BowBombArrow", new SingleWeaponAttackMode { Weapon = Bow, Ammo = BombArrow, FindWeapon = this.FindInventoryWeaponBow });
|
||||
|
|
|
@ -68,3 +68,72 @@ private func ExecuteMelee(effect fx)
|
|||
fx.Target->SetCommand("MoveTo", fx.target);
|
||||
return true;
|
||||
}
|
||||
|
||||
private func ExecuteClub(effect fx)
|
||||
{
|
||||
// Still carrying the melee weapon?
|
||||
if (fx.weapon->Contained() != fx.Target)
|
||||
{
|
||||
fx.weapon = nil;
|
||||
return false;
|
||||
}
|
||||
// Are we in range?
|
||||
var x=fx.Target->GetX(), y=fx.Target->GetY(), tx=fx.target->GetX(), ty=fx.target->GetY();
|
||||
var dx = tx-x, dy = ty-y;
|
||||
if (Abs(dx) <= 10 && PathFree(x,y,tx,ty))
|
||||
{
|
||||
if (Abs(dy) >= 15)
|
||||
{
|
||||
// Clonk is above or below us - wait
|
||||
if (dx<-5) fx.Target->SetComDir(COMD_Left); else if (dx>5) fx.Target->SetComDir(COMD_Right); else fx.Target->SetComDir(COMD_None);
|
||||
return true;
|
||||
}
|
||||
if (!this->CheckHandsAction(fx)) return true;
|
||||
// Stop here
|
||||
fx.Target->SetCommand("None"); fx.Target->SetComDir(COMD_None);
|
||||
// cooldown?
|
||||
if (!fx.weapon->CanStrikeWithWeapon(fx.Target))
|
||||
{
|
||||
//Message("MeleeWAIT %s @ %s!!!", fx.weapon->GetName(), fx.target->GetName());
|
||||
// While waiting for the cooldown, we try to evade...
|
||||
this->ExecuteEvade(fx,dx,dy);
|
||||
return true;
|
||||
}
|
||||
// OK, attack! Prefer upwards strike
|
||||
dy -= 16;
|
||||
fx.weapon->ControlUseStart(fx.Target, dx,dy);
|
||||
fx.weapon->ControlUseHolding(fx.Target, dx,dy);
|
||||
fx.weapon->ControlUseStop(fx.Target, dx,dy);
|
||||
return true;
|
||||
}
|
||||
// Not in range. Walk there.
|
||||
if (!fx.Target->GetCommand() || !Random(10)) fx.Target->SetCommand("MoveTo", fx.target);
|
||||
//Message("Melee %s @ %s!!!", fx.weapon->GetName(), fx.target->GetName());
|
||||
return true;
|
||||
}
|
||||
|
||||
private func ExecuteBomber(effect fx)
|
||||
{
|
||||
// Still carrying the bomb?
|
||||
if (fx.weapon->Contained() != fx.Target)
|
||||
{
|
||||
fx.weapon=nil;
|
||||
return false;
|
||||
}
|
||||
// Are we in range?
|
||||
if (fx.Target->ObjectDistance(fx.target) < 20 && !fx.weapon->OnFire())
|
||||
{
|
||||
// make sure it kills the AI clonk, because it would be useless after the explosion
|
||||
fx.Target->DoEnergy(5 - fx.Target->GetEnergy());
|
||||
// Boom!
|
||||
fx.weapon.TimeToExplode = 10;
|
||||
fx.weapon->Incinerate(100, fx.Target->GetController());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not in range. Walk there.
|
||||
if (!fx.Target->GetCommand() || !Random(10))
|
||||
fx.Target->SetCommand("MoveTo", fx.target);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -549,11 +549,21 @@ public func FindInventoryWeapon(effect fx)
|
|||
return true;
|
||||
}
|
||||
// Melee weapons.
|
||||
if ((fx.weapon = fx.Target->FindContents(Sword)) || (fx.weapon = fx.Target->FindContents(Club)) || (fx.weapon = fx.Target->FindContents(Axe)))
|
||||
if ((fx.weapon = fx.Target->FindContents(Sword)) || (fx.weapon = fx.Target->FindContents(Axe))) // Sword attacks aren't 100% correct for Axe, but work well enough
|
||||
{
|
||||
fx.strategy = this.ExecuteMelee;
|
||||
return true;
|
||||
}
|
||||
if ((fx.weapon = fx.Target->FindContents(PowderKeg)))
|
||||
{
|
||||
fx.strategy = this.ExecuteBomber;
|
||||
return true;
|
||||
}
|
||||
if ((fx.weapon = fx.Target->FindContents(Club)))
|
||||
{
|
||||
fx.strategy = this.ExecuteClub;
|
||||
return true;
|
||||
}
|
||||
// No weapon.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include Library_CarryHeavy
|
||||
|
||||
local count;
|
||||
local TimeToExplode = 90; // Number of frames to pass until keg explodes
|
||||
|
||||
public func GetCarryTransform(clonk)
|
||||
{
|
||||
|
@ -101,7 +102,7 @@ public func Incineration(int caused_by)
|
|||
public func FxFuseTimer(object target, effect, int timer)
|
||||
{
|
||||
CreateParticle("Fire", 0, 0, PV_Random(-10, 10), PV_Random(-20, 10), PV_Random(10, 40), Particles_Glimmer(), 6);
|
||||
if (timer > 90)
|
||||
if (timer > TimeToExplode)
|
||||
Explode(GetExplosionStrength());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue