openclonk/planet/Experimental.ocd/FireGlobe.ocd/Script.c

207 lines
3.4 KiB
C

/*
FireGlobe
Author: Newton
*/
local sx,sy,ex,ey;
local vis;
local aimed;
func Construction()
{
vis = nil;
aimed = false;
}
func ControlUse(object clonk, int x, int y)
{
if(!aimed) return false;
// fire fireball
var angle = Angle(0,0,x,y);
Exit();
Launch(angle,120,clonk);
SetDivert(sx,sy,ex,ey);
return true;
}
func ControlUseStart(object clonk, int x, int y)
{
if(aimed) return false;
sx = x+clonk->GetX();
sy = y+clonk->GetY();
if(vis) vis->RemoveObject();
vis = CreateObjectAbove(VisualPath,0,0,clonk->GetOwner());
vis->Set(sx,sy,x+clonk->GetX(),y+clonk->GetY());
vis["Visibility"]=VIS_Owner;
return true;
}
func HoldingEnabled() { return true; }
func ControlUseHolding(object clonk, int x, int y)
{
if(aimed) return false;
if(vis) vis->Set(sx,sy,x+clonk->GetX(),y+clonk->GetY());
}
func ControlUseStop(object clonk, int x, int y)
{
if(aimed) return false;
ex = x+clonk->GetX();
ey = y+clonk->GetY();
vis->Set(sx,sy,ex,ey);
aimed=true;
return true;
}
public func DelLine()
{
if(vis) vis->RemoveObject();
}
public func Deselection()
{
DelLine();
}
public func Destruction()
{
DelLine();
}
public func Launch(int angle, int str, object shooter)
{
var xdir = Sin(angle,str);
var ydir = Cos(angle,-str);
SetXDir(xdir);
SetYDir(ydir);
AddEffect("HitCheck", this, 1,1, nil,nil, shooter);
AddEffect("InFlight", this, 1,1, this);
}
public func SetDivert(int x1, int y1, int x2, int y2)
{
var inflight = GetEffect("InFlight",this);
inflight.ax = x1;
inflight.ay = y1;
inflight.bx = x2;
inflight.by = y2;
inflight.freeflight = true;
}
public func HitObject(object obj)
{
Hit();
}
public func Hit()
{
DelLine();
Explode(20);
}
// rotate arrow according to speed
public func FxInFlightStart(object target, effect, int temp)
{
if(temp) return;
effect.x = target->GetX();
effect.y = target->GetY();
}
public func FxInFlightTimer(object target, effect, int time)
{
var oldx = effect.x;
var oldy = effect.y;
var newx = target->GetX();
var newy = target->GetY();
if(effect.freeflight)
{
var ax = effect.ax;
var ay = effect.ay;
var bx = effect.bx;
var by = effect.by;
var pos = Intersect(oldx, oldy, newx, newy, ax, ay, bx, by);
if (pos != nil)
{
var angle = Angle(ax, ay, bx, by);
var speed = 60;
target->SetXDir(Sin(angle,speed));
target->SetYDir(-Cos(angle, speed));
effect.freeflight = false;
}
}
effect.x = newx;
effect.y = newy;
}
// Returns nil or coordinates of intersection.
global func Intersect(int Ax, int Ay, int Bx, int By, int Px, int Py, int Qx, int Qy)
{
var BAx = Bx-Ax;
var BAy = By-Ay;
var PAx = Px-Ax;
var PAy = Py-Ay;
var QPx = Qx-Px;
var QPy = Qy-Py;
var denominator = (BAy*QPx - BAx*QPy);
var numerator = (BAx*PAy - BAy*PAx);
// parallel!
if(denominator == 0)
{
if(numerator != 0) return nil;
// on same line somewhere
else
{
return [Ax, Ay];
}
}
// in parameter bounds?
var Y = 10000 * numerator/denominator;
if(!Inside(Y,0,10000)) return nil;
// we don't want division by zero...
if(BAy != 0) {
numerator = (PAy + Y*QPy/10000);
denominator = BAy;
}
else if(BAx != 0) {
numerator = (PAx + Y*QPx/10000);
denominator = BAx;
}
// in parameter bounds
var X = 10000*numerator / denominator;
if(!Inside(X,0,10000)) return nil;
// this is the point...
var x = Ax+X*(BAx)/10000;
var y = Ay+X*(BAy)/10000;
return [x, y];
}
local Name = "$Name$";
local Collectible = 1;