Urho3D/bin/Data/Scripts/NinjaSnowWar/Ninja.as

335 lines
12 KiB
ActionScript

#include "Scripts/NinjaSnowWar/GameObject.as"
#include "Scripts/NinjaSnowWar/AIController.as"
const int LAYER_MOVE = 0;
const int LAYER_ATTACK = 1;
const float ninjaMoveForce = 25;
const float ninjaAirMoveForce = 1;
const float ninjaDampingForce = 5;
const float ninjaJumpForce = 450;
const Vector3 ninjaThrowVelocity(0, 4.25, 20);
const Vector3 ninjaThrowPosition(0, 0.2, 1);
const float ninjaThrowDelay = 0.1;
const float ninjaCorpseDuration = 3;
const int ninjaPoints = 250;
class Ninja : GameObject
{
Controls controls;
Controls prevControls;
AIController@ controller;
bool okToJump;
bool smoke;
float inAirTime;
float onGroundTime;
float throwTime;
float deathTime;
float deathDir;
float dirChangeTime;
float aimX;
float aimY;
Ninja()
{
health = maxHealth = 2;
okToJump = false;
smoke = false;
onGround = false;
isSliding = false;
inAirTime = 1;
onGroundTime = 0;
throwTime = 0;
deathTime = 0;
deathDir = 0;
dirChangeTime = 0;
aimX = 0;
aimY = 0;
}
void DelayedStart()
{
SubscribeToEvent(node, "NodeCollision", "HandleNodeCollision");
// Get horizontal aim from initial rotation
aimX = controls.yaw = node.rotation.yaw;
// Start playing the idle animation immediately, even before the first physics update
AnimationController@ animCtrl = node.children[0].GetComponent("AnimationController");
animCtrl.PlayExclusive("Models/NinjaSnowWar/Ninja_Idle3.ani", LAYER_MOVE, true);
}
void SetControls(const Controls&in newControls)
{
controls = newControls;
}
Quaternion GetAim()
{
Quaternion q = Quaternion(aimX, Vector3(0, 1, 0));
q = q * Quaternion(aimY, Vector3(1, 0, 0));
return q;
}
void FixedUpdate(float timeStep)
{
// For multiplayer, replicate the health into the node user variables
node.vars["Health"] = health;
if (health <= 0)
{
DeathUpdate(timeStep);
return;
}
// AI control if controller exists
if (controller !is null)
controller.Control(this, node, timeStep);
RigidBody@ body = node.GetComponent("RigidBody");
AnimationController@ animCtrl = node.children[0].GetComponent("AnimationController");
// Turning / horizontal aiming
if (aimX != controls.yaw)
aimX = controls.yaw;
// Vertical aiming
if (aimY != controls.pitch)
aimY = controls.pitch;
// Force the physics rotation
Quaternion q(aimX, Vector3(0, 1, 0));
body.rotation = q;
// Movement ground/air
Vector3 vel = body.linearVelocity;
if (onGround)
{
// If landed, play a particle effect at feet (use the AnimatedModel node)
if (inAirTime > 0.5)
SpawnParticleEffect(node.children[0].worldPosition, "Particle/SnowExplosion.xml", 1);
inAirTime = 0;
onGroundTime += timeStep;
}
else
{
onGroundTime = 0;
inAirTime += timeStep;
}
if (inAirTime < 0.3f && !isSliding)
{
bool sideMove = false;
// Movement in four directions
if (controls.IsDown(CTRL_UP|CTRL_DOWN|CTRL_LEFT|CTRL_RIGHT))
{
float animDir = 1.0f;
Vector3 force(0, 0, 0);
if (controls.IsDown(CTRL_UP))
force += q * Vector3(0, 0, 1);
if (controls.IsDown(CTRL_DOWN))
{
animDir = -1.0f;
force += q * Vector3(0, 0, -1);
}
if (controls.IsDown(CTRL_LEFT))
{
sideMove = true;
force += q * Vector3(-1, 0, 0);
}
if (controls.IsDown(CTRL_RIGHT))
{
sideMove = true;
force += q * Vector3(1, 0, 0);
}
// Normalize so that diagonal strafing isn't faster
force.Normalize();
force *= ninjaMoveForce;
body.ApplyImpulse(force);
// Walk or sidestep animation
if (sideMove)
{
animCtrl.PlayExclusive("Models/NinjaSnowWar/Ninja_Stealth.ani", LAYER_MOVE, true, 0.2);
animCtrl.SetSpeed("Models/NinjaSnowWar/Ninja_Stealth.ani", animDir * 2.2);
}
else
{
animCtrl.PlayExclusive("Models/NinjaSnowWar/Ninja_Walk.ani", LAYER_MOVE, true, 0.2);
animCtrl.SetSpeed("Models/NinjaSnowWar/Ninja_Walk.ani", animDir * 1.6);
}
}
else
{
// Idle animation
animCtrl.PlayExclusive("Models/NinjaSnowWar/Ninja_Idle3.ani", LAYER_MOVE, true, 0.2);
}
// Overall damping to cap maximum speed
body.ApplyImpulse(Vector3(-ninjaDampingForce * vel.x, 0, -ninjaDampingForce * vel.z));
// Jumping
if (controls.IsDown(CTRL_JUMP))
{
if (okToJump && inAirTime < 0.1f)
{
// Lift slightly off the ground for better animation
body.position = body.position + Vector3(0, 0.03, 0);
body.ApplyImpulse(Vector3(0, ninjaJumpForce, 0));
inAirTime = 1.0f;
animCtrl.PlayExclusive("Models/NinjaSnowWar/Ninja_JumpNoHeight.ani", LAYER_MOVE, false, 0.1);
animCtrl.SetTime("Models/NinjaSnowWar/Ninja_JumpNoHeight.ani", 0.0); // Always play from beginning
okToJump = false;
}
}
else okToJump = true;
}
else
{
// Motion in the air
// Note: when sliding a steep slope, control (or damping) isn't allowed!
if (inAirTime > 0.3f && !isSliding)
{
if (controls.IsDown(CTRL_UP|CTRL_DOWN|CTRL_LEFT|CTRL_RIGHT))
{
Vector3 force(0, 0, 0);
if (controls.IsDown(CTRL_UP))
force += q * Vector3(0, 0, 1);
if (controls.IsDown(CTRL_DOWN))
force += q * Vector3(0, 0, -1);
if (controls.IsDown(CTRL_LEFT))
force += q * Vector3(-1, 0, 0);
if (controls.IsDown(CTRL_RIGHT))
force += q * Vector3(1, 0, 0);
// Normalize so that diagonal strafing isn't faster
force.Normalize();
force *= ninjaAirMoveForce;
body.ApplyImpulse(force);
}
}
// Falling/jumping/sliding animation
if (inAirTime > 0.1f)
animCtrl.PlayExclusive("Models/NinjaSnowWar/Ninja_JumpNoHeight.ani", LAYER_MOVE, false, 0.1);
}
// Shooting
if (throwTime >= 0)
throwTime -= timeStep;
// Start fading the attack animation after it has progressed past a certain point
if (animCtrl.GetTime("Models/NinjaSnowWar/Ninja_Attack1.ani") > 0.1)
animCtrl.Fade("Models/NinjaSnowWar/Ninja_Attack1.ani", 0.0, 0.5);
if ((controls.IsPressed(CTRL_FIRE, prevControls)) && (throwTime <= 0))
{
Vector3 projectileVel = GetAim() * ninjaThrowVelocity;
animCtrl.Play("Models/NinjaSnowWar/Ninja_Attack1.ani", LAYER_ATTACK, false, 0.0);
animCtrl.SetTime("Models/NinjaSnowWar/Ninja_Attack1.ani", 0.0); // Always play from beginning
Node@ snowball = SpawnObject(node.position + vel * timeStep + q * ninjaThrowPosition, GetAim(), "SnowBall");
RigidBody@ snowballBody = snowball.GetComponent("RigidBody");
snowballBody.linearVelocity = projectileVel;
GameObject@ snowballObject = cast<GameObject>(snowball.scriptObject);
snowballObject.side = side;
snowballObject.creatorID = node.id;
PlaySound("Sounds/NutThrow.wav");
throwTime = ninjaThrowDelay;
}
prevControls = controls;
ResetWorldCollision();
}
void DeathUpdate(float timeStep)
{
RigidBody@ body = node.GetComponent("RigidBody");
CollisionShape@ shape = node.GetComponent("CollisionShape");
Node@ modelNode = node.children[0];
AnimationController@ animCtrl = modelNode.GetComponent("AnimationController");
AnimatedModel@ model = modelNode.GetComponent("AnimatedModel");
Vector3 vel = body.linearVelocity;
// Overall damping to cap maximum speed
body.ApplyImpulse(Vector3(-ninjaDampingForce * vel.x, 0, -ninjaDampingForce * vel.z));
// Collide only to world geometry
body.collisionMask = 2;
// Pick death animation on first death update
if (deathDir == 0)
{
if (Random(1.0) < 0.5)
deathDir = -1;
else
deathDir = 1;
PlaySound("Sounds/SmallExplosion.wav");
VariantMap eventData;
eventData["Points"] = ninjaPoints;
eventData["Receiver"] = lastDamageCreatorID;
eventData["DamageSide"] = lastDamageSide;
SendEvent("Points", eventData);
SendEvent("Kill", eventData);
}
deathTime += timeStep;
// Move the model node to center the corpse mostly within the physics cylinder
// (because of the animation)
if (deathDir < 0)
{
// Backward death
animCtrl.StopLayer(LAYER_ATTACK, 0.1);
animCtrl.PlayExclusive("Models/NinjaSnowWar/Ninja_Death1.ani", LAYER_MOVE, false, 0.2);
animCtrl.SetSpeed("Models/NinjaSnowWar/Ninja_Death1.ani", 0.5);
if ((deathTime >= 0.3) && (deathTime < 0.8))
modelNode.Translate(Vector3(0, 0, 4.25 * timeStep));
}
else if (deathDir > 0)
{
// Forward death
animCtrl.StopLayer(LAYER_ATTACK, 0.1);
animCtrl.PlayExclusive("Models/NinjaSnowWar/Ninja_Death2.ani", LAYER_MOVE, false, 0.2);
animCtrl.SetSpeed("Models/NinjaSnowWar/Ninja_Death2.ani", 0.5);
if ((deathTime >= 0.4) && (deathTime < 0.8))
modelNode.Translate(Vector3(0, 0, -4.25 * timeStep));
}
// Create smokecloud just before vanishing
if ((deathTime > (ninjaCorpseDuration - 1)) && (!smoke))
{
SpawnParticleEffect(node.position + Vector3(0, -0.4, 0), "Particle/Smoke.xml", 8);
smoke = true;
}
if (deathTime > ninjaCorpseDuration)
{
SpawnObject(node.position + Vector3(0, -0.5, 0), Quaternion(), "LightFlash");
SpawnSound(node.position + Vector3(0, -0.5, 0), "Sounds/BigExplosion.wav", 2);
node.Remove();
}
}
bool Heal(int amount)
{
if (health == maxHealth)
return false;
health += amount;
if (health > maxHealth)
health = maxHealth;
// If player, play the "powerup" sound
if (side == SIDE_PLAYER)
PlaySound("Sounds/Powerup.wav");
return true;
}
}