forked from Mirrors/openclonk
move AI ranged and melee control to separate files
parent
7fb300896a
commit
3282806d7d
|
@ -1,5 +1,5 @@
|
|||
[DefCore]
|
||||
id=AI
|
||||
Version=6,0
|
||||
Version=8,0
|
||||
Category=C4D_None | C4D_MouseIgnore
|
||||
HideInCreator=true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[DefCore]
|
||||
id=AI_HelperFunctions
|
||||
Version=6,0
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
HideInCreator=true
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[DefCore]
|
||||
id=AI_MeleeWeapons
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
HideInCreator=true
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
AI Melee Weapons
|
||||
Functionality that helps the AI use melee weapons. Handles:
|
||||
* Sword
|
||||
|
||||
@author Sven2, Maikel
|
||||
*/
|
||||
|
||||
|
||||
/*-- General Melee Weapon --*/
|
||||
|
||||
private func ExecuteMelee(effect fx)
|
||||
{
|
||||
// Still carrying the melee weapon?
|
||||
if (fx.weapon->Contained() != this)
|
||||
{
|
||||
fx.weapon = nil;
|
||||
return false;
|
||||
}
|
||||
// Are we in range?
|
||||
var x = GetX(), y = 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 (dy >= -15)
|
||||
{
|
||||
// Target is under us - sword slash downwards!
|
||||
if (!this->CheckHandsAction(fx))
|
||||
return true;
|
||||
// Stop here.
|
||||
SetCommand("None");
|
||||
SetComDir(COMD_None);
|
||||
// Cooldown?
|
||||
if (!fx.weapon->CanStrikeWithWeapon(this))
|
||||
{
|
||||
// While waiting for the cooldown, we try to evade...
|
||||
this->ExecuteEvade(fx, dx, dy);
|
||||
return true;
|
||||
}
|
||||
// OK, slash!
|
||||
this->SelectItem(fx.weapon);
|
||||
return fx.weapon->ControlUse(this, tx,ty);
|
||||
}
|
||||
// Clonk is above us - jump there.
|
||||
this->ExecuteJump();
|
||||
if (dx<-5)
|
||||
SetComDir(COMD_Left);
|
||||
else if (dx > 5)
|
||||
SetComDir(COMD_Right);
|
||||
else
|
||||
SetComDir(COMD_None);
|
||||
}
|
||||
// Not in range. Walk there.
|
||||
if (!GetCommand() || !Random(10))
|
||||
SetCommand("MoveTo", fx.target);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
[DefCore]
|
||||
id=AI_RangedWeapons
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
HideInCreator=true
|
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
AI Ranged Weapons
|
||||
Functionality that helps the AI use ranged weapons. Handles:
|
||||
* Bow
|
||||
* Blunderbuss
|
||||
* Grenade launcher
|
||||
|
||||
@author Sven2, Maikel
|
||||
*/
|
||||
|
||||
|
||||
/*-- General Ranged Weapon --*/
|
||||
|
||||
private func ExecuteRanged(effect fx)
|
||||
{
|
||||
// Still carrying the bow?
|
||||
if (fx.weapon->Contained() != this)
|
||||
{
|
||||
fx.weapon = fx.post_aim_weapon = nil;
|
||||
return false;
|
||||
}
|
||||
// Finish shooting process.
|
||||
if (fx.post_aim_weapon)
|
||||
{
|
||||
// Wait max one second after shot (otherwise may be locked in wait animation forever if something goes wrong during shot).
|
||||
if (FrameCounter() - fx.post_aim_weapon_time < 36)
|
||||
if (this->IsAimingOrLoading())
|
||||
return true;
|
||||
fx.post_aim_weapon = nil;
|
||||
}
|
||||
// Target still in guard range?
|
||||
if (!this->CheckTargetInGuardRange(fx))
|
||||
return false;
|
||||
// Look at target.
|
||||
this->ExecuteLookAtTarget(fx);
|
||||
// Make sure we can shoot.
|
||||
if (!this->IsAimingOrLoading() || !fx.aim_weapon)
|
||||
{
|
||||
this->CancelAiming(fx);
|
||||
if (!this->CheckHandsAction(fx)) return true;
|
||||
// Start aiming.
|
||||
this->SelectItem(fx.weapon);
|
||||
if (!fx.weapon->ControlUseStart(this, fx.target->GetX()-GetX(), fx.target->GetY()-GetY())) return false; // something's broken :(
|
||||
fx.aim_weapon = fx.weapon;
|
||||
fx.aim_time = fx.time;
|
||||
fx.post_aim_weapon = nil;
|
||||
// Enough for now.
|
||||
return;
|
||||
}
|
||||
// Stuck in aim procedure check?
|
||||
if (GetEffect("IntAimCheckProcedure", this) && !this->ReadyToAction())
|
||||
return this->ExecuteStand(fx);
|
||||
// Calculate offset to target. Take movement into account.
|
||||
// Also aim for the head (y-4) so it's harder to evade by jumping.
|
||||
var x = GetX(), y = GetY(), tx = fx.target->GetX(), ty = fx.target->GetY() - 4;
|
||||
var d = Distance(x, y, tx, ty);
|
||||
// Projected travel time of the arrow.
|
||||
var dt = d * 10 / fx.projectile_speed;
|
||||
tx += this->GetTargetXDir(fx.target, dt);
|
||||
ty += this->GetTargetYDir(fx.target, dt);
|
||||
if (!fx.target->GetContact(-1))
|
||||
if (!fx.target->GetCategory() & C4D_StaticBack)
|
||||
ty += GetGravity() * dt * dt / 200;
|
||||
// Path to target free?
|
||||
if (PathFree(x, y, tx, ty))
|
||||
{
|
||||
// Get shooting angle.
|
||||
var shooting_angle;
|
||||
if (fx.ranged_direct)
|
||||
shooting_angle = Angle(x, y, tx, ty, 10);
|
||||
else
|
||||
shooting_angle = this->GetBallisticAngle(tx-x, ty-y, fx.projectile_speed, 160);
|
||||
if (GetType(shooting_angle) != C4V_Nil)
|
||||
{
|
||||
// No ally on path? Also search for allied animals, just in case.
|
||||
var ally;
|
||||
if (!fx.ignore_allies) ally = FindObject(Find_OnLine(0,0,tx-x,ty-y), Find_Exclude(this), Find_OCF(OCF_Alive), Find_Owner(GetOwner()));
|
||||
if (ally)
|
||||
{
|
||||
// Try to jump, if not possible just wait.
|
||||
if (this->ExecuteJump())
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Aim / shoot there.
|
||||
x = Sin(shooting_angle, 1000, 10);
|
||||
y = -Cos(shooting_angle, 1000, 10);
|
||||
fx.aim_weapon->ControlUseHolding(this, x, y);
|
||||
if (this->IsAiming() && fx.time >= fx.aim_time + fx.aim_wait)
|
||||
{
|
||||
fx.aim_weapon->ControlUseStop(this, x, y);
|
||||
// Assign post-aim status to allow slower shoot animations to pass.
|
||||
fx.post_aim_weapon = fx.aim_weapon;
|
||||
fx.post_aim_weapon_time = FrameCounter();
|
||||
fx.aim_weapon = nil;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Path not free or out of range. Just wait for enemy to come...
|
||||
fx.aim_weapon->ControlUseHolding(this, tx - x, ty - y);
|
||||
// Might also change target if current is unreachable.
|
||||
var new_target;
|
||||
if (!Random(3))
|
||||
if (new_target = this->FindTarget(fx))
|
||||
fx.target = new_target;
|
||||
return true;
|
||||
}
|
||||
|
||||
private func IsAimingOrLoading() { return !!GetEffect("IntAim*", this); }
|
||||
|
||||
|
||||
/*-- Bow --*/
|
||||
|
||||
private func HasArrows(effect fx, object weapon)
|
||||
{
|
||||
if (weapon->Contents(0))
|
||||
return true;
|
||||
if (FindObject(Find_Container(this), Find_Func("IsArrow")))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*-- Blunderbuss --*/
|
||||
|
||||
private func HasAmmo(effect fx, object weapon)
|
||||
{
|
||||
if (weapon->Contents(0))
|
||||
return true;
|
||||
if (FindObject(Find_Container(this), Find_Func("IsBullet")))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*-- Grenade Launcher --*/
|
||||
|
||||
private func HasBombs(effect fx, object weapon)
|
||||
{
|
||||
if (weapon->Contents(0))
|
||||
return true;
|
||||
if (FindObject(Find_Container(this), Find_Func("IsGrenadeLauncherAmmo")))
|
||||
return true;
|
||||
return false;
|
||||
}
|
|
@ -6,9 +6,13 @@
|
|||
*/
|
||||
|
||||
|
||||
// Include the different parts of the AI.
|
||||
#include AI_HelperFunctions
|
||||
#include AI_MeleeWeapons
|
||||
#include AI_RangedWeapons
|
||||
#include AI_Vehicles
|
||||
|
||||
// General settings of the AI, these can be modified per script for the specific AI clonk.
|
||||
static const AI_DefMaxAggroDistance = 200, // Lose sight to target if it is this far away (unles we're ranged - then always guard the range rect).
|
||||
AI_DefGuardRangeX = 300, // Search targets this far away in either direction (searching in rectangle).
|
||||
AI_DefGuardRangeY = 150, // Search targets this far away in either direction (searching in rectangle).
|
||||
|
@ -38,11 +42,13 @@ public func AddAI(object clonk)
|
|||
{
|
||||
var fx = GetEffect("AI", clonk);
|
||||
if (!fx) fx = AddEffect("AI", clonk, 1, 3, nil, AI);
|
||||
if (!fx || !clonk) return nil;
|
||||
if (!fx || !clonk)
|
||||
return nil;
|
||||
fx.ai = AI;
|
||||
clonk.ExecuteAI = AI.Execute;
|
||||
clonk.ai = fx;
|
||||
if (clonk->GetProcedure() == "PUSH") fx.vehicle = clonk->GetActionTarget();
|
||||
if (clonk->GetProcedure() == "PUSH")
|
||||
fx.vehicle = clonk->GetActionTarget();
|
||||
BindInventory(clonk);
|
||||
SetHome(clonk);
|
||||
SetGuardRange(clonk, fx.home_x-AI_DefGuardRangeX, fx.home_y-AI_DefGuardRangeY, AI_DefGuardRangeX*2, AI_DefGuardRangeY*2);
|
||||
|
@ -451,106 +457,6 @@ private func CancelAiming(effect fx)
|
|||
return true;
|
||||
}
|
||||
|
||||
private func IsAimingOrLoading() { return !!GetEffect("IntAim*", this); }
|
||||
|
||||
private func ExecuteRanged(effect fx)
|
||||
{
|
||||
// Still carrying the bow?
|
||||
if (fx.weapon->Contained() != this)
|
||||
{
|
||||
fx.weapon = fx.post_aim_weapon = nil;
|
||||
return false;
|
||||
}
|
||||
// Finish shooting process.
|
||||
if (fx.post_aim_weapon)
|
||||
{
|
||||
// Wait max one second after shot (otherwise may be locked in wait animation forever if something goes wrong during shot).
|
||||
if (FrameCounter() - fx.post_aim_weapon_time < 36)
|
||||
if (IsAimingOrLoading())
|
||||
return true;
|
||||
fx.post_aim_weapon = nil;
|
||||
}
|
||||
// Target still in guard range?
|
||||
if (!CheckTargetInGuardRange(fx))
|
||||
return false;
|
||||
// Look at target.
|
||||
ExecuteLookAtTarget(fx);
|
||||
// Make sure we can shoot.
|
||||
if (!IsAimingOrLoading() || !fx.aim_weapon)
|
||||
{
|
||||
CancelAiming(fx);
|
||||
if (!CheckHandsAction(fx)) return true;
|
||||
// Start aiming.
|
||||
SelectItem(fx.weapon);
|
||||
if (!fx.weapon->ControlUseStart(this, fx.target->GetX()-GetX(), fx.target->GetY()-GetY())) return false; // something's broken :(
|
||||
fx.aim_weapon = fx.weapon;
|
||||
fx.aim_time = fx.time;
|
||||
fx.post_aim_weapon = nil;
|
||||
// Enough for now.
|
||||
return;
|
||||
}
|
||||
// Stuck in aim procedure check?
|
||||
if (GetEffect("IntAimCheckProcedure", this) && !this->ReadyToAction())
|
||||
return ExecuteStand(fx);
|
||||
// Calculate offset to target. Take movement into account.
|
||||
// Also aim for the head (y-4) so it's harder to evade by jumping.
|
||||
var x = GetX(), y = GetY(), tx = fx.target->GetX(), ty = fx.target->GetY() - 4;
|
||||
var d = Distance(x, y, tx, ty);
|
||||
// Projected travel time of the arrow.
|
||||
var dt = d * 10 / fx.projectile_speed;
|
||||
tx += GetTargetXDir(fx.target, dt);
|
||||
ty += GetTargetYDir(fx.target, dt);
|
||||
if (!fx.target->GetContact(-1))
|
||||
if (!fx.target->GetCategory() & C4D_StaticBack)
|
||||
ty += GetGravity() * dt * dt / 200;
|
||||
// Path to target free?
|
||||
if (PathFree(x, y, tx, ty))
|
||||
{
|
||||
// Get shooting angle.
|
||||
var shooting_angle;
|
||||
if (fx.ranged_direct)
|
||||
shooting_angle = Angle(x, y, tx, ty, 10);
|
||||
else
|
||||
shooting_angle = GetBallisticAngle(tx-x, ty-y, fx.projectile_speed, 160);
|
||||
if (GetType(shooting_angle) != C4V_Nil)
|
||||
{
|
||||
// No ally on path? Also search for allied animals, just in case.
|
||||
var ally;
|
||||
if (!fx.ignore_allies) ally = FindObject(Find_OnLine(0,0,tx-x,ty-y), Find_Exclude(this), Find_OCF(OCF_Alive), Find_Owner(GetOwner()));
|
||||
if (ally)
|
||||
{
|
||||
if (ExecuteJump())
|
||||
return true;
|
||||
// Can't jump and ally is in the way. just wait.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Aim / shoot there.
|
||||
x = Sin(shooting_angle, 1000, 10);
|
||||
y = -Cos(shooting_angle, 1000, 10);
|
||||
fx.aim_weapon->ControlUseHolding(this, x, y);
|
||||
if (this->IsAiming() && fx.time >= fx.aim_time + fx.aim_wait)
|
||||
{
|
||||
fx.aim_weapon->ControlUseStop(this, x, y);
|
||||
// Assign post-aim status to allow slower shoot animations to pass.
|
||||
fx.post_aim_weapon = fx.aim_weapon;
|
||||
fx.post_aim_weapon_time = FrameCounter();
|
||||
fx.aim_weapon = nil;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Path not free or out of range. Just wait for enemy to come...
|
||||
fx.aim_weapon->ControlUseHolding(this, tx - x, ty - y);
|
||||
// Might also change target if current is unreachable.
|
||||
var new_target;
|
||||
if (!Random(3))
|
||||
if (new_target = FindTarget(fx))
|
||||
fx.target = new_target;
|
||||
return true;
|
||||
}
|
||||
|
||||
private func ExecuteLookAtTarget(effect fx)
|
||||
{
|
||||
// Set direction to look at target, we can assume this is instantanuous.
|
||||
|
@ -654,53 +560,6 @@ private func ExecuteStand(effect fx)
|
|||
return true;
|
||||
}
|
||||
|
||||
private func ExecuteMelee(effect fx)
|
||||
{
|
||||
// Still carrying the melee weapon?
|
||||
if (fx.weapon->Contained() != this)
|
||||
{
|
||||
fx.weapon = nil;
|
||||
return false;
|
||||
}
|
||||
// Are we in range?
|
||||
var x = GetX(), y = 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 (dy >= -15)
|
||||
{
|
||||
// Target is under us - sword slash downwards!
|
||||
if (!CheckHandsAction(fx))
|
||||
return true;
|
||||
// Stop here.
|
||||
SetCommand("None");
|
||||
SetComDir(COMD_None);
|
||||
// Cooldown?
|
||||
if (!fx.weapon->CanStrikeWithWeapon(this))
|
||||
{
|
||||
// While waiting for the cooldown, we try to evade...
|
||||
ExecuteEvade(fx, dx, dy);
|
||||
return true;
|
||||
}
|
||||
// OK, slash!
|
||||
SelectItem(fx.weapon);
|
||||
return fx.weapon->ControlUse(this, tx,ty);
|
||||
}
|
||||
// Clonk is above us - jump there.
|
||||
ExecuteJump();
|
||||
if (dx<-5)
|
||||
SetComDir(COMD_Left);
|
||||
else if (dx > 5)
|
||||
SetComDir(COMD_Right);
|
||||
else
|
||||
SetComDir(COMD_None);
|
||||
}
|
||||
// Not in range. Walk there.
|
||||
if (!GetCommand() || !Random(10))
|
||||
SetCommand("MoveTo", fx.target);
|
||||
return true;
|
||||
}
|
||||
|
||||
private func ExecuteEvade(effect fx, int threat_dx, int threat_dy)
|
||||
{
|
||||
// Evade from threat at position delta threat_dx, threat_dy.
|
||||
|
@ -732,7 +591,7 @@ private func ExecuteArm(effect fx)
|
|||
// Find shield.
|
||||
fx.shield = FindContents(Shield);
|
||||
// Find a weapon. For now, just search own inventory.
|
||||
if (FindInventoryWeapon(fx) && fx.weapon->Contained()==this)
|
||||
if (FindInventoryWeapon(fx) && fx.weapon->Contained() == this)
|
||||
{
|
||||
SelectItem(fx.weapon);
|
||||
return true;
|
||||
|
@ -826,33 +685,6 @@ private func FindInventoryWeapon(effect fx)
|
|||
return false;
|
||||
}
|
||||
|
||||
private func HasArrows(effect fx, object weapon)
|
||||
{
|
||||
if (weapon->Contents(0))
|
||||
return true;
|
||||
if (FindObject(Find_Container(this), Find_Func("IsArrow")))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private func HasAmmo(effect fx, object weapon)
|
||||
{
|
||||
if (weapon->Contents(0))
|
||||
return true;
|
||||
if (FindObject(Find_Container(this), Find_Func("IsBullet")))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private func HasBombs(effect fx, object weapon)
|
||||
{
|
||||
if (weapon->Contents(0))
|
||||
return true;
|
||||
if (FindObject(Find_Container(this), Find_Func("IsGrenadeLauncherAmmo")))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private func ExecuteIdle(effect fx)
|
||||
{
|
||||
if (!Inside(GetX() - fx.home_x, -5, 5) || !Inside(GetY() - fx.home_y, -15, 15))
|
||||
|
|
|
@ -2,23 +2,23 @@ GuardRange=Bewachter Bereich
|
|||
MaxAggroDistance=Angriffsradius
|
||||
IgnoreAllies=Mitspieler ignorieren
|
||||
Active=Aktiv
|
||||
ActiveHelp=Ob die KI aktiv den Clonk momentan steuert. Eine inaktive KI kann ueber die Aktion 'KI aktivieren' zum Beispiel in einer Sequenz wieder aktiviert werden.
|
||||
ActiveHelp=Ob die KI aktiv den Clonk momentan steuert. Eine inaktive KI kann über die Aktion 'KI aktivieren' zum Beispiel in einer Sequenz wieder aktiviert werden.
|
||||
AutoSearchTarget=Ziel automatisch suchen
|
||||
AutoSearchTargetHelp=Wenn wahr, sucht die KI automatisch Gegner. Ansonsten muss der Gegner per Sequenzbefehl gegeben werden.
|
||||
Enemy=Gegner
|
||||
EnemyHelp=Welcher Gegner angegriffen werden soll. Wenn nicht angegeben, greift der Gegner den naechsten Clonk an.
|
||||
EnemyHelp=Welcher Gegner angegriffen werden soll. Wenn nicht angegeben, greift der Gegner den nächsten Clonk an.
|
||||
SetAIActivated=KI aktivieren
|
||||
SetAIActivatedHelp=Aktiviert die Gegner-KI fuer ein Objekt. Wenn keine KI aktiviert ist, wird sie fuer das Objekt erstellt.
|
||||
SetAIActivatedHelp=Aktiviert die Gegner-KI für ein Objekt. Wenn keine KI aktiviert ist, wird sie für das Objekt erstellt.
|
||||
AttackTarget=Angriffsziel
|
||||
AttackTargetHelp=Wenn angegeben, greift der KI-Clonk direkt diesen Gegner an.
|
||||
Status=Aktiviert
|
||||
StatusHelp=Ob die KI aktiviert oder deaktiviert wird.
|
||||
SetAINewHome=KI Position setzen
|
||||
SetAINewHomeHelp=Laesst einen KI-Gegner an eine neue Position laufen.
|
||||
SetAINewHomeHelp=Lässt einen KI-Gegner an eine neue Position laufen.
|
||||
NewHome=Neue Position
|
||||
NewHomeHelp=Wohin der Clonk laufen soll.
|
||||
NewHomeDir=Richtung
|
||||
NewHomeDirHelp=In welche Richtung der KI-Clonk schauen soll, wenn kein Gegner in der Naehe ist.
|
||||
Unchanged=Ungeaendert
|
||||
NewHomeDirHelp=In welche Richtung der KI-Clonk schauen soll, wenn kein Gegner in der Nähe ist.
|
||||
Unchanged=Ungeändert
|
||||
Left=Links
|
||||
Right=Rechts
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[DefCore]
|
||||
id=AI_Vehicles
|
||||
Version=6,0
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
HideInCreator=true
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
AI Vehicles
|
||||
Functionality that helps the AI use vehicles.
|
||||
Functionality that helps the AI use vehicles. Handles:
|
||||
* Catapult
|
||||
|
||||
@author Sven2, Maikel
|
||||
*/
|
||||
|
@ -50,7 +51,7 @@ private func ExecuteCatapult(effect fx)
|
|||
return true;
|
||||
}
|
||||
// Target still in guard range?
|
||||
if (!fx.ai->CheckTargetInGuardRange(fx))
|
||||
if (!this->CheckTargetInGuardRange(fx))
|
||||
return false;
|
||||
// Turn in correct direction.
|
||||
var x = GetX(), y = GetY(), tx = fx.target->GetX(), ty = fx.target->GetY() - 4;
|
||||
|
@ -79,8 +80,8 @@ private func ExecuteCatapult(effect fx)
|
|||
var dx = tx - x, dy = ty - y + 20;
|
||||
var power = Sqrt((GetGravity() * dx * dx) / Max(Abs(dx) + dy, 1));
|
||||
var dt = dx * 10 / power;
|
||||
tx += fx.ai->GetTargetXDir(fx.target, dt);
|
||||
ty += fx.ai->GetTargetYDir(fx.target, dt);
|
||||
tx += this->GetTargetXDir(fx.target, dt);
|
||||
ty += this->GetTargetYDir(fx.target, dt);
|
||||
if (!fx.target->GetContact(-1))
|
||||
dy += GetGravity() * dt * dt / 200;
|
||||
power = Sqrt((GetGravity() * dx * dx) / Max(Abs(dx) + dy, 1));
|
||||
|
|
Loading…
Reference in New Issue