clean up grapple bow scripts

shapetextures
Maikel de Vries 2015-12-25 16:10:52 +01:00
parent de3ed60aa8
commit e4b1fe94ca
6 changed files with 388 additions and 399 deletions

View File

@ -9,7 +9,6 @@
#include Library_Rope
static const Weight = 1;
static const Library_Rope_MAXLENGTH = 1000;
// Call this to break the rope.
@ -71,8 +70,6 @@ public func HookRemoved()
func FxIntHangTimer() { TimeStep(); }
local last_point;
func UpdateLines()
{
var oldangle;
@ -120,7 +117,6 @@ func UpdateLines()
else diff = Vec_Div(Vec_Mul(old_diff, length),o_length);
diffangle = Vec_Angle(diff, [0,0]);
point = Vec_Add(start, Vec_Div(diff, 2));
last_point = point;
}
lib_rope_segments[i]->SetGraphics(nil);
@ -131,13 +127,13 @@ func UpdateLines()
}
}
func GetHookAngle()
public func GetHookAngle()
{
if(lib_rope_particle_count > 3)
return Angle(lib_rope_particles[-2].x, lib_rope_particles[-2].y, lib_rope_particles[-3].x, lib_rope_particles[-3].y)+180;
}
func SetLineTransform(obj, int r, int xoff, int yoff, int length, int layer, int MirrorSegments) {
public func SetLineTransform(obj, int r, int xoff, int yoff, int length, int layer, int MirrorSegments) {
if(!MirrorSegments) MirrorSegments = 1;
var fsin=Sin(r, 1000), fcos=Cos(r, 1000);
// set matrix values
@ -174,19 +170,18 @@ func ForcesOnObjects()
if(redo) redo --;
}
var j = 0;
if(PullObjects() )
for(var i = 0; i < 2; i++)
if (PullObjects())
for (var i = 0; i < 2; i++)
{
if(i == 1) j = lib_rope_particle_count-1;
if (i == 1) j = lib_rope_particle_count-1;
var obj = lib_rope_objects[i][0];
if(obj == nil || !lib_rope_objects[i][1]) continue;
if (obj == nil || !lib_rope_objects[i][1]) continue;
if(obj->Contained()) obj = obj->Contained();
if (obj->Contained())
obj = obj->Contained();
if( (obj->GetAction() == "Walk" || obj->GetAction() == "Scale" || obj->GetAction() == "Hangle"))
obj->SetAction("Jump");
if( obj->GetAction() == "Climb")
if (obj->GetAction() == "Walk" || obj->GetAction() == "Scale" || obj->GetAction() == "Hangle" || obj->GetAction() == "Climb")
obj->SetAction("Jump");
var xdir = BoundBy(lib_rope_particles[j].x-lib_rope_particles[j].oldx, -100, 100);
@ -223,11 +218,11 @@ func ForcesOnObjects()
// Altered to function in 'ConnectPull' mode
public func ConstraintObjects()
{
if(lib_rope_length < GetMaxLength()) // in the rope library this is
{
for(var i = 0, i2 = 0; i < 2; i++ || i2--)
SetParticleToObject(i2, i);
}
if(lib_rope_length < GetMaxLength()) // in the rope library this is
{
for (var i = 0, i2 = 0; i < 2; i++ || i2--)
SetParticleToObject(i2, i);
}
}
// This is called constantly by the lift tower as long as something is reeled in

View File

@ -1,22 +1,17 @@
/*
/**
Grapple Hook
Author: Randrian
The hook can be shot with the grappling bow. On impact the hook will stick to the ground.
The hook also controls the swinging controls for the clonk.
The hook can be shot with the grappling bow.
On impact the hook will stick to the ground
The hook also controls the swinging controls for the clonk
@author Randrian
*/
local rope; // The rope is the connection between the hook
local rope; // The rope is the connection between the hook and the bow.
local clonk;
local pull;
local grappler;
local fx_hook;
local Plane = 300;
public func ArrowStrength() { return 10; }
public func GetRope() { return rope; }
public func New(object new_clonk, object new_rope)
@ -31,18 +26,18 @@ public func Launch(int angle, int str, object shooter, object bow)
SetObjDrawTransform(0, 1, 0, 0, 0, 0, 0); // Hide
Exit();
pull = 0;
pull = false;
// Create rope
rope = CreateObjectAbove(GrappleRope, 0, 0, NO_OWNER);
// Create rope.
rope = CreateObject(GrappleRope);
rope->Connect(this, bow);
rope->ConnectLoose();
clonk = shooter;
grappler = bow;
var xdir = Sin(angle,str);
var ydir = Cos(angle,-str);
var xdir = Sin(angle, str);
var ydir = Cos(angle, -str);
SetXDir(xdir);
SetYDir(ydir);
SetR(angle);
@ -53,7 +48,7 @@ public func Launch(int angle, int str, object shooter, object bow)
public func Destruction()
{
if(rope)
if (rope)
rope->HookRemoved();
}
@ -62,8 +57,7 @@ private func Stick()
if (GetEffect("InFlight",this))
{
Sound("Objects::Arrow::HitGround");
RemoveEffect("InFlight",this);
RemoveEffect("InFlight", this);
SetXDir(0);
SetYDir(0);
@ -81,22 +75,22 @@ private func Stick()
SetVertex(6, VTX_X, -4, 2);
SetVertex(6, VTX_Y, -1, 2);
rope->HockAnchored();
rope->HookAnchored();
// Draw in possible other active grapplers the clonk is using once this hook hits a solid area and sticks.
for (var obj in FindObjects(Find_ID(GrappleBow), Find_Container(clonk)))
if (obj != grappler)
obj->DrawRopeIn();
ScheduleCall(this, "StartPull", 5); // TODO
}
}
public func StartPull()
{
pull = 1;
pull = true;
fx_hook = AddEffect("IntGrappleControl", clonk, 1, 1, this);
if(clonk->GetAction() == "Jump")
if (clonk->GetAction() == "Jump")
{
rope->AdjustClonkMovement();
rope->ConnectPull();
@ -105,43 +99,43 @@ public func StartPull()
}
}
public func Hit(x, y)
public func Hit()
{
Stick();
}
// rotate arrow according to speed
public func FxInFlightStart(object target, effect, int temp)
public func FxInFlightStart(object target, proplist effect, int temp)
{
if(temp) return;
effect.x = target->GetX();
effect.y = target->GetY();
}
public func FxInFlightTimer(object target, effect, int time)
public func FxInFlightTimer(object target, proplist effect, int time)
{
var oldx = effect.x;
var oldy = effect.y;
var newx = GetX();
var newy = GetY();
// and additionally, we need one check: If the arrow has no speed
// and additionally, we need one check: If the hook has no speed
// anymore but is still in flight, we'll remove the hit check
if(oldx == newx && oldy == newy)
if (oldx == newx && oldy == newy)
{
// but we give the arrow 5 frames to speed up again
effect.countdown++;
if(effect.countdown >= 10)
if (effect.countdown >= 10)
return Hit();
}
else
effect.countdown = 0;
// rotate arrow according to speed
var anglediff = Normalize(Angle(oldx,oldy,newx,newy)-GetR(),-180);
SetRDir(anglediff/2);
// Rotate hook according to speed
var anglediff = Normalize(Angle(oldx, oldy ,newx, newy) - GetR(), -180);
SetRDir(anglediff / 2);
effect.x = newx;
effect.y = newy;
return;
return FX_OK;
}
public func Entrance(object container)
@ -155,111 +149,108 @@ public func Entrance(object container)
public func OnRopeBreak()
{
// Only remove control effect if it is available, otherwise if fx_hook == nil RemoveEffect removes some other effect.
// Remove control effect for the grapple bow, but only if it exists.
// Otherwise RemoveEffect with fx_hook == nil removes another effect in the clonk.
if (fx_hook)
RemoveEffect(nil, clonk, fx_hook);
RemoveObject();
return;
}
local Name = "$Name$";
/*-- Grapple rope controls --*/
public func FxIntGrappleControlControl(object target, fxnum, ctrl, x,y,strength, repeat, release)
public func FxIntGrappleControlControl(object target, proplist effect, int ctrl, int x, int y, int strength, repeat, release)
{
// Cancel this effect if clonk is now attached to something
if (target->GetProcedure() == "ATTACH") {
RemoveEffect(nil,target,fxnum);
// Cancel this effect if clonk is now attached to something.
if (target->GetProcedure() == "ATTACH")
{
RemoveEffect(nil, target, effect);
return false;
}
if(ctrl != CON_Up && ctrl != CON_Down && ctrl != CON_Right && ctrl != CON_Left) return false;
if (ctrl != CON_Up && ctrl != CON_Down && ctrl != CON_Right && ctrl != CON_Left)
return false;
if(ctrl == CON_Right)
if (ctrl == CON_Right)
{
fxnum.mv_right = !release;
if(release)
effect.mv_right = !release;
if (release)
{
if(fxnum.lastkey == CON_Right)
{
target->SetDir(0);
target->UpdateTurnRotation();
}
fxnum.lastkey = CON_Right;
fxnum.keyTimer = 10;
if (effect.lastkey == CON_Right)
{
target->SetDir(0);
target->UpdateTurnRotation();
}
effect.lastkey = CON_Right;
effect.keyTimer = 10;
}
}
if(ctrl == CON_Left)
if (ctrl == CON_Left)
{
fxnum.mv_left = !release;
if(release)
effect.mv_left = !release;
if (release)
{
if(fxnum.lastkey == CON_Left)
{
target->SetDir(1);
target->UpdateTurnRotation();
}
fxnum.lastkey = CON_Left;
fxnum.keyTimer = 10;
if (effect.lastkey == CON_Left)
{
target->SetDir(1);
target->UpdateTurnRotation();
}
effect.lastkey = CON_Left;
effect.keyTimer = 10;
}
}
if(ctrl == CON_Up)
if (ctrl == CON_Up)
{
fxnum.mv_up = !release;
effect.mv_up = !release;
if ((target->GetAction() == "Jump" || target->GetAction() == "WallJump") && !release && pull)
rope->ConnectPull();
}
if(ctrl == CON_Down)
if (ctrl == CON_Down)
{
fxnum.mv_down = !release;
effect.mv_down = !release;
}
// never swallow the control
// Never swallow the control.
return false;
}
local iSwingAnimation;
// Effect for smooth movement.
public func FxIntGrappleControlTimer(object target, fxnum, int time)
public func FxIntGrappleControlTimer(object target, proplist effect, int time)
{
// Cancel this effect if clonk is now attached to something
// this check is also in the timer because on a high control rate
// (higher than 1 actually), the timer could be called first
if (target->GetProcedure() == "ATTACH")
return -1;
return FX_Execute_Kill;
// Also cancel if the clonk is contained
if (target->Contained())
return -1;
return FX_Execute_Kill;
if(fxnum.keyTimer)
if (effect.keyTimer)
{
fxnum.keyTimer--;
if(fxnum.keyTimer == 0)
fxnum.lastkey = 0;
effect.keyTimer--;
if (effect.keyTimer == 0)
effect.lastkey = 0;
}
// Movement.
if (fxnum.mv_up)
if (rope)
if (effect.mv_up && rope)
{
var iSpeed = 10-Cos(target->GetAnimationPosition(fxnum.Climb)*360*2/target->GetAnimationLength("RopeClimb")-45, 10);
fxnum.speedCounter += iSpeed;
if(fxnum.speedCounter > 20)
{
rope->DoLength(-1);
fxnum.speedCounter -= 20;
var iSpeed = 10 - Cos(target->GetAnimationPosition(effect.Climb) * 360 * 2 / target->GetAnimationLength("RopeClimb") - 45, 10);
effect.speedCounter += iSpeed;
if (effect.speedCounter > 20)
{
rope->DoLength(-1);
effect.speedCounter -= 20;
}
}
if (fxnum.mv_down)
if (effect.mv_down)
if (rope)
rope->DoLength(+1);
if (fxnum.mv_left)
if (effect.mv_left)
{
rope->DoSpeed(-10);
}
if (fxnum.mv_right)
if (effect.mv_right)
{
rope->DoSpeed(+10);
}
@ -273,105 +264,103 @@ public func FxIntGrappleControlTimer(object target, fxnum, int time)
rope->ConnectLoose();
}
if ((target->GetAction() == "Jump" || target->GetAction() == "WallJump") && rope->PullObjects() && !fxnum.var6)
if ((target->GetAction() == "Jump" || target->GetAction() == "WallJump") && rope->PullObjects() && !effect.var6)
{
if(!fxnum.ani_mode)
if (!effect.ani_mode)
{
target->SetTurnType(1);
if(!target->GetHandAction())
if (!target->GetHandAction())
target->SetHandAction(-1);
}
/* target->SetObjDrawTransform(1000, 0, 3000, 0, 1000);
if(target->GetDir())
SetObjDrawTransform(1000, 0, -3000, 0, 1000);*/
if(fxnum.mv_up)
if (effect.mv_up)
{
if(fxnum.ani_mode != 2)
if (effect.ani_mode != 2)
{
fxnum.ani_mode = 2;
fxnum.Climb = target->PlayAnimation("RopeClimb", CLONK_ANIM_SLOT_Arms, Anim_Linear(target->GetAnimationLength("RopeClimb")/2, 0, target->GetAnimationLength("RopeClimb"), 35), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
fxnum.speedCounter = 0;
effect.ani_mode = 2;
effect.Climb = target->PlayAnimation("RopeClimb", CLONK_ANIM_SLOT_Arms, Anim_Linear(target->GetAnimationLength("RopeClimb")/2, 0, target->GetAnimationLength("RopeClimb"), 35), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
effect.speedCounter = 0;
}
}
else if(fxnum.mv_down)
else if (effect.mv_down)
{
if(fxnum.ani_mode != 3)
if (effect.ani_mode != 3)
{
fxnum.ani_mode = 3;
effect.ani_mode = 3;
target->PlayAnimation("RopeDown", CLONK_ANIM_SLOT_Arms, Anim_Const(0), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
}
}
else if(fxnum.mv_left || fxnum.mv_right)
else if (effect.mv_left || effect.mv_right)
{
var start = target->GetAnimationLength("RopeSwing")/2;
var length = target->GetAnimationLength("RopeSwing");
var start = length / 2;
var dir = 0;
if( (fxnum.mv_left && !target->GetDir())
|| (!fxnum.mv_left && target->GetDir())
) dir = 1;
if(fxnum.ani_mode != 4+dir)
if ((effect.mv_left && !target->GetDir()) || (!effect.mv_left && target->GetDir()))
dir = 1;
if (effect.ani_mode != 4 + dir)
{
iSwingAnimation = target->PlayAnimation("RopeSwing", CLONK_ANIM_SLOT_Arms, Anim_Linear(start, length*dir, length*(!dir), 35, ANIM_Hold), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
fxnum.ani_mode = 4+dir;
target->PlayAnimation("RopeSwing", CLONK_ANIM_SLOT_Arms, Anim_Linear(start, length * dir, length*(!dir), 35, ANIM_Hold), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
effect.ani_mode = 4 + dir;
}
}
else if(fxnum.ani_mode != 1)
else if (effect.ani_mode != 1)
{
fxnum.ani_mode = 1;
target->PlayAnimation("OnRope", CLONK_ANIM_SLOT_Arms, Anim_Linear(0, 0, target->GetAnimationLength("OnRope"), 35*2, ANIM_Loop), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
effect.ani_mode = 1;
target->PlayAnimation("OnRope", CLONK_ANIM_SLOT_Arms, Anim_Linear(0, 0, target->GetAnimationLength("OnRope"), 35 * 2, ANIM_Loop), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
}
var angle = rope->GetClonkAngle();
var off = rope->GetClonkOff();
// off = [0,0];
//var pos = rope->GetClonkPos();
//target->SetPosition(pos[0], pos[1], nil, LIB_ROPE_Precision);
target.MyAngle = angle;
//angle = 0;
target->SetMeshTransformation(Trans_Translate(-off[0]*10+3000*(1-2*target->GetDir()),-off[1]*10), 2);
target->SetMeshTransformation(Trans_RotX(angle,500,11000),3);//-6000,12000), 3);
target->SetMeshTransformation(Trans_Translate(-off[0] * 10 + 3000 * (1 - 2 * target->GetDir()), -off[1] * 10), 2);
target->SetMeshTransformation(Trans_RotX(angle, 500, 11000), 3);
}
else if(fxnum.ani_mode)
else if (effect.ani_mode)
{
target->SetMeshTransformation(0, 2);
target->SetMeshTransformation(0, 3);
// target->SetObjDrawTransform(1000, 0, 0, 0, 1000);
target->SetMeshTransformation(0, 3);
target->StopAnimation(target->GetRootAnimation(10));
if(!target->GetHandAction())
target->SetHandAction(0);
fxnum.ani_mode = 0;
if (!target->GetHandAction())
target->SetHandAction(0);
effect.ani_mode = 0;
}
if(fxnum.var6) fxnum.var6--;
if (effect.var6)
effect.var6--;
return FX_OK;
}
global func Trans_RotX(int rotation, int ox, int oy)
private func Trans_RotX(int rotation, int ox, int oy)
{
return Trans_Mul(Trans_Translate(-ox, -oy), Trans_Rotate(rotation, 0, 0, 1), Trans_Translate(ox, oy));
}
public func FxIntGrappleControlStop(object target, fxnum, int reason, int tmp)
public func FxIntGrappleControlStop(object target, proplist effect, int reason, int tmp)
{
if(tmp) return;
if (tmp)
return FX_OK;
target->SetTurnType(0);
target->SetMeshTransformation(0, 2);
target->SetMeshTransformation(0, 3);
target->StopAnimation(target->GetRootAnimation(10));
// target->SetObjDrawTransform();
if(!target->GetHandAction())
if (!target->GetHandAction())
target->SetHandAction(0);
// grapple hook == this:
// if the hook is not already drawing in, break the rope
// If the hook is not already drawing in, break the rope.
if (!GetEffect("DrawIn", this->GetRope()))
{
this->GetRope()->BreakRope();
}
return FX_OK;
}
public func RejectWindbagForce() { return true; }
// Only the grappler is stored.
public func SaveScenarioObject() { return false; }
/*-- Properties --*/
local Name = "$Name$";
local Plane = 300;

View File

@ -8,18 +8,19 @@
#include Library_Rope
static const Weight = 1;
local has_hook_anchored;
local last_point;
// Call this to break the rope.
public func BreakRope()
{
if(lib_rope_length == -1) return;
if (lib_rope_length == -1)
return;
lib_rope_length = -1;
var act1 = lib_rope_objects[0][0];
var act2 = lib_rope_objects[1][0];
SetAction("Idle");
// notify action targets.
// Notify action targets.
if (act1 != nil)
act1->~OnRopeBreak();
if (act2 != nil)
@ -29,12 +30,13 @@ public func BreakRope()
return;
}
/* --------------------- Callbacks from the rope ---------------------- */
/*-- Rope Callbacks --*/
/* To be overloaded for special segment behaviour */
// From the rope library: to be overloaded for special segment behaviour.
private func CreateSegment(int index, object previous)
{
if(index == 0) return;
if (index == 0)
return;
var segment;
segment = CreateObjectAbove(GrappleRope);
return segment;
@ -47,23 +49,18 @@ public func Connect(object obj1, object obj2)
{
StartRopeConnect(obj1, obj2);
SetMaxLength(100);
HoockAnchored = 0;
has_hook_anchored = false;
SetAction("Hide");
AddEffect("IntHang", this, 1, 1, this);
return;
}
public func GetConnectStatus() { return !lib_rope_length_auto; }
local HoockAnchored;
local DrawingIn;
// Callback form the hook, when it hits ground.
public func HockAnchored(bool pull)
public func HookAnchored()
{
HoockAnchored = 1;
has_hook_anchored = true;
}
public func HookRemoved()
@ -81,7 +78,7 @@ public func MaxLengthReached()
var clonk = lib_rope_objects[1][0];
if (clonk->Contained())
clonk = clonk->Contained();
if (!HoockAnchored)
if (!has_hook_anchored)
{
for (var i = 0; i < lib_rope_particle_count; i++)
{
@ -92,7 +89,7 @@ public func MaxLengthReached()
}
}
/* for swinging */
// Adjust speed on swinging.
public func DoSpeed(int value)
{
var speed = lib_rope_particles[-1].x - lib_rope_particles[-1].oldx;
@ -101,17 +98,17 @@ public func DoSpeed(int value)
lib_rope_particles[-1].oldx -= value;
}
func FxIntHangTimer() { TimeStep(); }
public func FxIntHangTimer() { TimeStep(); }
func FxDrawInTimer()
public func FxDrawInTimer()
{
if(lib_rope_length < 15)
if (lib_rope_length < 15)
{
BreakRope();
return -1;
}
DoLength(-5);
if (!HoockAnchored)
if (!has_hook_anchored)
{
for (var i = 0; i < lib_rope_particle_count; i++)
{
@ -122,9 +119,8 @@ func FxDrawInTimer()
}
}
func DrawIn(bool no_control)
public func DrawIn(bool no_control)
{
DrawingIn = 1;
if (!GetEffect("DrawIn", this))
{
AddEffect("DrawIn", this, 1, 1, this);
@ -145,7 +141,7 @@ func DrawIn(bool no_control)
}
}
func AdjustClonkMovement()
public func AdjustClonkMovement()
{
var clonk = lib_rope_objects[1][0];
if (clonk->Contained())
@ -163,14 +159,12 @@ func AdjustClonkMovement()
clonk->SetYDir(clonk_newspeed[1], LIB_ROPE_Precision);
}
local last_point;
func UpdateLines()
public func UpdateLines()
{
var oldangle;
for(var i=1; i < lib_rope_particle_count; i++)
for (var i = 1; i < lib_rope_particle_count; i++)
{
// Update the Position of the Segment
// Update the Position of the segment
lib_rope_segments[i]->SetPosition(GetPartX(i), GetPartY(i));
// Calculate the angle to the previous segment
@ -180,133 +174,143 @@ func UpdateLines()
var start = [lib_rope_particles[i-1].x, lib_rope_particles[i-1].y];
var end = [lib_rope_particles[i].x, lib_rope_particles[i].y];
if(i == 1 && lib_rope_particle_count > 2)
{
if (i == 1 && lib_rope_particle_count > 2)
{
angle = Angle(lib_rope_particles[2].x, lib_rope_particles[2].y, lib_rope_particles[0].x, lib_rope_particles[0].y);
end = [lib_rope_particles[0].x, lib_rope_particles[0].y];
end[0] += -Sin(angle, 45*LIB_ROPE_Precision/10);
end[1] += +Cos(angle, 45*LIB_ROPE_Precision/10);
end[0] += -Sin(angle, 45 * LIB_ROPE_Precision / 10);
end[1] += +Cos(angle, 45 * LIB_ROPE_Precision / 10);
}
if(i == 2)
if (i == 2)
{
angle = Angle(lib_rope_particles[2].x, lib_rope_particles[2].y, lib_rope_particles[0].x, lib_rope_particles[0].y);
start = [lib_rope_particles[0].x, lib_rope_particles[0].y];
start[0] += -Sin(angle, 45*LIB_ROPE_Precision/10);
start[1] += +Cos(angle, 45*LIB_ROPE_Precision/10);
start[0] += -Sin(angle, 45 * LIB_ROPE_Precision / 10);
start[1] += +Cos(angle, 45 * LIB_ROPE_Precision / 10);
}
var diff = Vec_Sub(end,start);
var diff = Vec_Sub(end, start);
var point = Vec_Add(start, Vec_Div(diff, 2));
var diffangle = Vec_Angle(diff, [0,0]);
var length = Vec_Length(diff)*1000/LIB_ROPE_Precision/10;
var length = Vec_Length(diff) * 1000 / LIB_ROPE_Precision / 10;
if(i == lib_rope_particle_count-1)
if (i == lib_rope_particle_count - 1)
{
var old = [lib_rope_particles[i-2].x, lib_rope_particles[i-2].y];
var old_diff = Vec_Sub(start,old);
var o_length = Vec_Length(old_diff)*1000/LIB_ROPE_Precision/10;
if(!o_length) diff = old_diff;
else diff = Vec_Div(Vec_Mul(old_diff, length),o_length);
diffangle = Vec_Angle(diff, [0,0]);
var old = [lib_rope_particles[i - 2].x, lib_rope_particles[i - 2].y];
var old_diff = Vec_Sub(start, old);
var o_length = Vec_Length(old_diff) * 1000 / LIB_ROPE_Precision / 10;
if (!o_length)
diff = old_diff;
else
diff = Vec_Div(Vec_Mul(old_diff, length), o_length);
point = Vec_Add(start, Vec_Div(diff, 2));
last_point = point;
}
if(i == 1)
var diffangle = Angle(diff[0], diff[1], 0, 0);
if (i == 1)
{
lib_rope_segments[i]->SetGraphics(nil, GrappleHook);
lib_rope_segments[i].MeshTransformation = Trans_Mul(Trans_Translate(1500,0,0),Trans_Scale(1500));
point[0] += -Cos(diffangle, 15*LIB_ROPE_Precision/10)+Sin(diffangle, 4*LIB_ROPE_Precision);
point[1] += -Cos(diffangle, 4*LIB_ROPE_Precision)-Sin(diffangle, 15*LIB_ROPE_Precision/10);
lib_rope_segments[i].MeshTransformation = Trans_Mul(Trans_Translate(1500, 0, 0), Trans_Scale(1500));
point[0] += -Cos(diffangle, 15 * LIB_ROPE_Precision / 10) + Sin(diffangle, 4 * LIB_ROPE_Precision);
point[1] += -Cos(diffangle, 4 * LIB_ROPE_Precision) - Sin(diffangle, 15 * LIB_ROPE_Precision / 10);
length = 1000;
}
SetLineTransform(lib_rope_segments[i], -diffangle, point[0]*10-GetPartX(i)*1000,point[1]*10-GetPartY(i)*1000, length );
SetLineTransform(lib_rope_segments[i], -diffangle, point[0] * 10 - GetPartX(i) * 1000, point[1] * 10 - GetPartY(i) * 1000, length);
// Remember the angle
// Remember the angle.
oldangle = angle;
}
return;
}
func GetClonkAngle()
public func GetClonkAngle()
{
if(lib_rope_particle_count > 3)
return Angle(lib_rope_particles[-2].x, lib_rope_particles[-2].y, lib_rope_particles[-3].x, lib_rope_particles[-3].y);
if (lib_rope_particle_count > 3)
return Angle(lib_rope_particles[-2].x, lib_rope_particles[-2].y, lib_rope_particles[-3].x, lib_rope_particles[-3].y);
return 0;
}
local ClonkOldSpeed;
func GetClonkPos()
public func GetClonkPos()
{
return [lib_rope_particles[-1].x, lib_rope_particles[-1].y];
}
func GetClonkOff()
public func GetClonkOff()
{
return Vec_Sub(GetClonkPos(), last_point);
}
func SetLineTransform(obj, int r, int xoff, int yoff, int length, int layer, int MirrorSegments) {
if(!MirrorSegments) MirrorSegments = 1;
var fsin=Sin(r, 1000), fcos=Cos(r, 1000);
// set matrix values
public func SetLineTransform(object obj, int r, int xoff, int yoff, int length, int layer, int mirror_segments)
{
if (!mirror_segments)
mirror_segments = 1;
var fsin = Sin(r, 1000), fcos = Cos(r, 1000);
// Set matrix values.
obj->SetObjDrawTransform (
+fcos*MirrorSegments, +fsin*length/1000, xoff,
-fsin*MirrorSegments, +fcos*length/1000, yoff,layer
+fcos * mirror_segments, +fsin * length / 1000, xoff,
-fsin * mirror_segments, +fcos * length / 1000, yoff, layer
);
}
/* --------------------- Overloaded from the rope library --------------------- */
/*-- Library Overloads --*/
func ForcesOnObjects()
public func ForcesOnObjects()
{
if(!lib_rope_length) return;
if (!lib_rope_length)
return;
var redo = LengthAutoTryCount();
while(lib_rope_length_auto && redo)
while (lib_rope_length_auto && redo)
{
var speed = Vec_Length(Vec_Sub([lib_rope_particles[-1].x, lib_rope_particles[-1].y], [lib_rope_particles[-1].oldx, lib_rope_particles[-1].oldy]));
if(lib_rope_length == GetMaxLength())
if (lib_rope_length == GetMaxLength())
{
if(ObjContact(lib_rope_objects[1][0]))
if (ObjContact(lib_rope_objects[1][0]))
speed = 40;
else speed = 100;
else
speed = 100;
}
if(speed > 150) DoLength(1);
else if(speed < 50) DoLength(-1); // TODO not just obj 1
else redo = 0;
if(redo) redo --;
if (speed > 150)
DoLength(1);
else if (speed < 50)
DoLength(-1); // TODO not just obj 1
else
redo = 0;
if (redo > 0)
redo --;
}
var j = 0;
if (PullObjects())
for(var i = 0; i < 2; i++)
{
if(i == 1) j = lib_rope_particle_count-1;
var obj = lib_rope_objects[i][0];
for (var i = 0; i < 2; i++)
{
if (i == 1)
j = lib_rope_particle_count-1;
var obj = lib_rope_objects[i][0];
if (obj == nil || !lib_rope_objects[i][1])
continue;
if(obj == nil || !lib_rope_objects[i][1]) continue;
if (obj->Contained())
obj = obj->Contained();
if(obj->Contained()) obj = obj->Contained();
if (obj->GetAction() == "Walk" || obj->GetAction() == "Scale" || obj->GetAction() == "Hangle" || obj->GetAction() == "Climb")
obj->SetAction("Jump");
if(obj->GetAction() == "Walk" || obj->GetAction() == "Scale" || obj->GetAction() == "Hangle" || obj->GetAction() == "Climb")
obj->SetAction("Jump");
var xdir = BoundBy(lib_rope_particles[j].x - lib_rope_particles[j].oldx, -300, 300);
var ydir = BoundBy(lib_rope_particles[j].y - lib_rope_particles[j].oldy, -300, 300);
var xdir = BoundBy(lib_rope_particles[j].x-lib_rope_particles[j].oldx, -300, 300);
var ydir = BoundBy(lib_rope_particles[j].y-lib_rope_particles[j].oldy, -300, 300);
obj->SetXDir( xdir, LIB_ROPE_Precision);
obj->SetYDir( ydir, LIB_ROPE_Precision);
obj->SetXDir(xdir, LIB_ROPE_Precision);
obj->SetYDir(ydir, LIB_ROPE_Precision);
}
}
}
// Only the grappler is stored.
public func SaveScenarioObject() { return false; }
func Definition(def)
{
def.LineColors = [RGB(66,33,00), RGB(66,33,00)];
}
local ActMap = {
Hide = {
Prototype = Action,

View File

@ -1,46 +1,151 @@
/*
/**
Grapple Bow
Author: Randrian
A crossbow which is enabled to fire grappling hooks, also has a winching system.
@author Randrian
*/
func Hit()
{
Sound("Hits::GeneralHit?");
}
local fAiming;
local is_aiming;
local animation_set;
local hook;
local hook_attach;
public func GetCarrySpecial(clonk) { if(fAiming) return "pos_hand2"; }
public func GetCarryBone2(clonk) { return "main2"; }
public func GetCarryMode(clonk) { if(hook && hook->Contained() == nil) return CARRY_Back; if(fAiming >= 0) return CARRY_Grappler; }
/* +++++++++++ Controls ++++++++++++++ */
// holding callbacks are made
public func HoldingEnabled() { return true; }
local animation_set;
private func Initialize()
{
// The aiming animation is done by adjusting the animation position to fit the angle.
animation_set = {
AimMode = AIM_Position, // The aiming animation is done by adjusting the animation position to fit the angle
AimMode = AIM_Position,
AnimationAim = "CrossbowAimArms",
AnimationShoot = nil,
ShootTime = 20,
TurnType = 1,
WalkSpeed = 84,
WalkBack = 56,
AimSpeed = 20, // the speed of aiming
AimSpeed = 20,
};
OnRopeBreak();
return;
}
/*-- Animations --*/
public func GetCarrySpecial(object clonk)
{
if (is_aiming)
return "pos_hand2";
}
public func GetCarryBone2(object clonk) { return "main2"; }
public func GetCarryMode(object clonk)
{
if (hook && !hook->Contained())
return CARRY_Back;
if (is_aiming)
return CARRY_Grappler;
}
public func GetAnimationSet() { return animation_set; }
/*-- Controls --*/
public func HoldingEnabled() { return true; }
public func RejectUse(object clonk)
{
// Burned?
if (GetCon() < 100)
return true;
// Able to cut the hook? Then never reject the use.
if (hook->Contained() != this)
return false;
return !clonk->HasHandAction();
}
public func ControlUseStart(object clonk, int x, int y)
{
// Cut rope, or otherwise remove helper object.
EnsureHook();
if (hook->Contained() != this)
{
var rope = hook->GetRope();
if (rope)
{
rope->DrawIn();
return true;
}
else
{
hook->Enter(this);
}
}
// Start aiming.
is_aiming = true;
ControlUseHolding(clonk, x, y);
FinishedLoading(clonk);
return true;
}
// Callback from the clonk when loading is finished
public func FinishedLoading(object clonk)
{
clonk->~StartAim(this);
return true;
}
public func ControlUseHolding(object clonk, int x, int y)
{
// Update the aiming angle on mouse movement.
var angle = Angle(0, 0, x, y);
angle = Normalize(angle, -180);
angle = BoundBy(angle, -160, 160);
clonk->SetAimPosition(angle);
return true;
}
// Stopping says the clonk to stop with aiming (he will go on untill he has finished loading and aiming at the given angle).
public func ControlUseStop(object clonk, int x, int y)
{
clonk->StopAim();
return true;
}
// Callback from the clonk, when he actually has stopped aiming.
public func FinishedAiming(object clonk, int angle)
{
// Only shoot if the bow did not burn in the meantime.
if (GetCon() < 100)
return false;
// Shoot the hook and detach the mesh from the bow.
EnsureHook();
hook->Exit();
hook->Launch(angle, 100, clonk, this);
hook_attach = nil;
DetachMesh(hook_attach);
Sound("Objects::Weapons::Bow::Shoot?");
// Open the hand to let the string go and play the fire animation.
PlayAnimation("Fire", 6, Anim_Linear(0, 0, GetAnimationLength("Fire"), animation_set["ShootTime"], ANIM_Hold), Anim_Const(1000));
clonk->StartShoot(this);
return true;
}
public func ControlUseCancel(object clonk, int x, int y)
{
clonk->CancelAiming();
return true;
}
/*-- Bow Mechanics --*/
public func SetHook(object new_hook)
{
hook = new_hook;
@ -48,14 +153,15 @@ public func SetHook(object new_hook)
private func EnsureHook()
{
// Create hook if it went missing
if(!hook) hook = CreateObjectAbove(GrappleHook, 0, 0, NO_OWNER);
// Create hook if it went missing.
if (!hook)
hook = CreateObject(GrappleHook);
return hook;
}
public func OnRopeBreak()
{
if(hook_attach)
if (hook_attach)
DetachMesh(hook_attach);
EnsureHook();
@ -94,7 +200,7 @@ private func Departure()
}
}
// If shot (e.g. by a cannon)
// If shot (e.g. by a cannon) the rope is drawn in.
public func LaunchProjectile()
{
if (hook)
@ -106,104 +212,12 @@ public func LaunchProjectile()
_inherited(...);
}
public func GetAnimationSet() { return animation_set; }
public func RejectUse(object clonk)
{
// Burned?
if (GetCon()<100) return true;
// able to cut the hook?
if(hook->Contained() != this) return false;
return !clonk->HasHandAction();
}
public func ControlUseStart(object clonk, int x, int y)
{
// Cut rope, or otherwise remove helper object.
EnsureHook();
if (hook->Contained() != this)
{
var rope = hook->GetRope();
if (rope)
{
rope->DrawIn();
return true;
}
else
{
hook->Enter(this);
}
}
// Start aiming
fAiming = 1;
ControlUseHolding(clonk, x, y);
FinishedLoading(clonk);
return true;
}
// Callback from the clonk when loading is finished
public func FinishedLoading(object clonk)
{
clonk->~StartAim(this);
return true;
}
// Update the angle on mouse movement
public func ControlUseHolding(object clonk, int x, int y)
{
// Save new angle
var angle = Angle(0,0,x,y);
angle = Normalize(angle,-180);
if(angle > 160) angle = 160;
if(angle < -160) angle = -160;
clonk->SetAimPosition(angle);
return true;
}
// Stopping says the clonk to stop with aiming (he will go on untill he has finished loading and aiming at the given angle)
public func ControlUseStop(object clonk, int x, int y)
{
clonk->StopAim();
return true;
}
// Callback from the clonk, when he actually has stopped aiming
public func FinishedAiming(object clonk, int angle)
{
if (GetCon()<100) return false;
EnsureHook();
DetachMesh(hook_attach);
hook_attach = nil;
hook->Exit();
hook->Launch(angle, 100, clonk, this);
DetachMesh(hook_attach);
Sound("Objects::Weapons::Bow::Shoot?");
// Open the hand to let the string go and play the fire animation
PlayAnimation("Fire", 6, Anim_Linear(0, 0, GetAnimationLength("Fire"), animation_set["ShootTime"], ANIM_Hold), Anim_Const(1000));
clonk->StartShoot(this);
return true;
}
public func ControlUseCancel(object clonk, int x, int y)
{
clonk->CancelAiming();
return true;
}
/* Destroyed by fire? Make it visible. */
/*-- Fire Effects --*/
private func Incineration()
{
// GrappleBow becomes unusable on incineration.
// Grapple bow becomes unusable on incineration.
if (hook)
{
var rope = hook->GetRope();
@ -217,7 +231,7 @@ private func Incineration()
private func Extinguishing()
{
// If extinguished on the same frame it got incinerated, make it usable again
if (GetCon()>=100)
if (GetCon() >= 100)
{
EnsureHook();
SetClrModulation();
@ -225,20 +239,29 @@ private func Extinguishing()
return _inherited(...);
}
/* ++++++++ Animation functions ++++++++ */
public func Reset(clonk)
/*-- Animation functions --*/
public func Reset(object clonk)
{
fAiming = 0;
is_aiming = 0;
clonk->StopAnimation(clonk->GetRootAnimation(11));
StopAnimation(GetRootAnimation(6));
}
public func Hit()
{
Sound("Hits::GeneralHit?");
}
public func IsInventorProduct() { return true; }
func Definition(def) {
SetProperty("PictureTransformation",Trans_Mul(Trans_Translate(-700,400),Trans_Scale(1150),Trans_Rotate(180,0,1,0),Trans_Rotate(-30,-1,0,-1)),def);
/*-- Properties --*/
public func Definition(proplist def)
{
SetProperty("PictureTransformation", Trans_Mul(Trans_Translate(-700, 400), Trans_Scale(1150), Trans_Rotate(180, 0, 1, 0), Trans_Rotate(-30, -1, 0, -1)), def);
}
local Name = "$Name$";

View File

@ -422,10 +422,7 @@ private func SatisfyConstraints()
if (!lib_rope_particles[i].friction)
continue;
lib_rope_particles[i].oldx = (lib_rope_particles[i].oldx + lib_rope_particles[i].x) / 2;
lib_rope_particles[i].oldy = (lib_rope_particles[i].oldy + lib_rope_particles[i].y) / 2;
/*var newvel = Vec_Sub(lib_rope_particles[i][0], lib_rope_particles[i][1]);
newvel = Vec_Div(newvel, 2);
lib_rope_particles[i][1] = Vec_Sub(lib_rope_particles[i][0], newvel);*/
lib_rope_particles[i].oldy = (lib_rope_particles[i].oldy + lib_rope_particles[i].y) / 2;
}
return;
}
@ -450,15 +447,15 @@ public func ConstraintLength()
restlength = normal_restlength;
if (i == lib_rope_particle_count - 2)
restlength = GetLastLength();
// Get coordinates and inverse masses.
invmass1 = lib_rope_particles[i].mass;
invmass2 = lib_rope_particles[i + 1].mass;
// Calculate difference.
delta1 = lib_rope_particles[i + 1].x - lib_rope_particles[i].x;
delta2 = lib_rope_particles[i + 1].y - lib_rope_particles[i].y;
delta_length = Sqrt(delta1**2 + delta2**2);
if (delta_length < restlength)
continue;
continue;
// Get coordinates and inverse masses.
invmass1 = lib_rope_particles[i].mass;
invmass2 = lib_rope_particles[i + 1].mass;
delta1 = delta1 * (delta_length - restlength) / (delta_length * (invmass1 + invmass2));
delta2 = delta2 * (delta_length - restlength) / (delta_length * (invmass1 + invmass2));
// Set new positions.
@ -618,10 +615,10 @@ public func Vec_Angle(array x, array y) { return Angle(x[0], x[1], y[0], y[1]);
public func Vec_Normalize(array x, int precision) { return Vec_Div(Vec_Mul(x, precision), Vec_Length(x)); }
// Gives the the rounded x coordinate of particles index.
public func GetPartX(index) { return (lib_rope_particles[index].x + LIB_ROPE_Precision / 2) / LIB_ROPE_Precision; }
public func GetPartX(int index) { return (lib_rope_particles[index].x + LIB_ROPE_Precision / 2) / LIB_ROPE_Precision; }
// Gives the the rounded y coordinate of particles index.
public func GetPartY(index) { return (lib_rope_particles[index].y + LIB_ROPE_Precision / 2) / LIB_ROPE_Precision; }
public func GetPartY(int index) { return (lib_rope_particles[index].y + LIB_ROPE_Precision / 2) / LIB_ROPE_Precision; }
/*-- Helper Functions --*/

View File

@ -31,12 +31,7 @@ public func Initialize()
CreateObjectAbove(Ropeladder, 602, 158)->Unroll(1, -1);
// Profile.
//ProfileObject(Ropebridge);
ProfileObject(Ropeladder);
//StartScriptProfiler();
//ArrayAccess();
//ProplistAccess();
//StopScriptProfiler();
return;
}
@ -55,17 +50,3 @@ global func ProfileObject(id def, int duration)
StartScriptProfiler(def);
ScheduleCall(nil, "StopScriptProfiler", duration * 36, 0);
}
global func ArrayAccess()
{
var a = [[[0,0]]], c;
for (var i = 0; i < 10**6; i++)
c = a[0][0][0];
}
global func ProplistAccess()
{
var a = [{x = 1}], c;
for (var i = 0; i < 10**6; i++)
c = a[0].x;
}