openclonk/planet/Objects.ocd/Structures.ocd/StoneDoor.ocd/Script.c

234 lines
4.8 KiB
C

/**
Stone Door
A door which can be used in scenarios with lots of bricks.
@authors Ringwaul, Maikel
*/
#include Library_SwitchTarget
protected func Initialize()
{
SetAction("Door");
SetComDir(COMD_Stop);
return;
}
/*-- Movement --*/
public func OpenDoor()
{
ForceDigFree();
SetComDir(COMD_Up);
Sound("Structures::StoneGate::GateMove");
return;
}
public func CloseDoor()
{
ForceDigFree();
SetComDir(COMD_Down);
Sound("Structures::StoneGate::GateMove");
return;
}
private func IsOpen()
{
if (GetContact(-1) & CNAT_Top)
return true;
return false;
}
private func IsClosed()
{
if (GetContact(-1) & CNAT_Bottom)
return true;
return false;
}
protected func Hit()
{
Sound("Structures::StoneGate::GateHit");
return;
}
// Digs away earth behind the door. Needs to temporarily disable the solid mask, though.
private func ForceDigFree()
{
SetSolidMask();
DigFreeRect(GetX() - 4, GetY() - 20, 8, 40, true);
SetSolidMask(0, 0, 8, 40);
}
/*-- Switch control --*/
// Reaction to operation by a switch: if open_door is true the door opens, otherwise it closes
public func OnSetInputSignal(object operator, object switch, bool open_door)
{
if (open_door)
{
OpenDoor();
}
else
{
CloseDoor();
}
_inherited(operator, switch, open_door, ...);
}
/*-- Automatic movement --*/
// Overrules owner control and only let's the team through.
public func SetAutoControl(int team)
{
var effect = AddEffect("AutoControl", this, 100, 3, this);
effect.Team = team;
return;
}
protected func FxAutoControlTimer(object target, effect, int time)
{
var d = 0;
if (IsOpen())
d = 30;
var owner = GetOwner();
var team = effect.Team;
var open_door = false;
// Team control
if (team != nil)
for (var clonk in FindObjects(Find_OCF(OCF_CrewMember), Find_InRect(-50, d - 30, 100, 60)))
{
var plr = clonk->GetOwner();
var plr_team = GetPlayerTeam(plr);
if (team == 0 || plr_team == team)
open_door = true;
}
// Player control
else
if (FindObject(Find_OCF(OCF_CrewMember), Find_InRect(-50, d - 30, 100, 60), Find_Allied(owner)))
open_door = true;
// Keep door closed if hostile?
// TODO?
if (open_door && IsClosed())
OpenDoor();
if (!open_door && IsOpen())
CloseDoor();
return 1;
}
func FxAutoControlSaveScen(obj, fx, props)
{
props->AddCall("AutoControl", obj, "SetAutoControl", fx.team);
return true;
}
/*-- Destruction --*/
private func GetStrength() { return 180; }
protected func Damage()
{
// Destroy if damage above strength.
if (GetDamage() > GetStrength())
{
var particles =
{
Size = PV_KeyFrames(0, 0, 0, 100, PV_Random(3, 5), 1000, 3),
R = PV_Random(230, 250),
G = PV_Random(210, 230),
B = PV_Random(190, 210),
Alpha = PV_Linear(255, 0),
ForceY = PV_Gravity(100),
CollisionVertex = 0
};
CreateParticle("SmokeDirty", PV_Random(-4, 4), PV_Random(-18, 18), PV_Random(-10, 10), PV_Random(-10, 10), PV_Random(10, 60), particles, 300);
CastObjects(Rock, 5, 20);
return RemoveObject();
}
// Change appearance.
DoGraphics();
return;
}
private func DoGraphics()
{
// Change appearance according to damage and strength.
if (GetDamage() > 3 * GetStrength() / 4)
SetGraphics("Cracked3");
else if (GetDamage() > GetStrength() / 2)
SetGraphics("Cracked2");
else if (GetDamage() > GetStrength() / 4)
SetGraphics("Cracked1");
else
SetGraphics("");
return;
}
public func GetFloorOffset()
{
// Searches downwards from the lowest vertex to the floor
var y_off;
for (y_off=0; !GBackSolid(0, 20+y_off); ++y_off)
if (y_off > 20) break; // max range
return y_off;
}
/* Editor */
local EditorActions = {
OpenDoor = { Name = "$DoorUp$", Command = "OpenDoor()" },
CloseDoor = { Name = "$DoorDown$", Command = "CloseDoor()" }
};
public func Definition(def, ...)
{
UserAction->AddEvaluator("Action", "Structure", "$DoorUp$", "$DoorUpDesc$", "open_door", [def, def.EvalAct_OpenDoor], { }, UserAction->GetObjectEvaluator("IsDoor", "$Door$", "$DoorTargetHelp$"), "Door");
UserAction->AddEvaluator("Action", "Structure", "$DoorDown$", "$DoorDownDesc$", "close_door", [def, def.EvalAct_CloseDoor], { }, UserAction->GetObjectEvaluator("IsDoor", "$Door$", "$DoorTargetHelp$"), "Door");
return _inherited(def, ...);
}
private func EvalAct_OpenDoor(props, context)
{
var door = UserAction->EvaluateValue("Object", props.Door, context);
if (door) door->~OpenDoor();
}
private func EvalAct_CloseDoor(props, context)
{
var door = UserAction->EvaluateValue("Object", props.Door, context);
if (door) door->~CloseDoor();
}
/* Properties */
public func IsDoor() { return true; }
local ActMap = {
Door = {
Prototype = Action,
Name = "Door",
Procedure = DFA_FLOAT,
Speed = 150,
Accel = 12,
Decel = 12,
Length = 1,
Delay = 1,
X = 0,
Y = 0,
Wdt = 8,
Hgt = 40,
NextAction = "Door",
},
};
local Name = "$Name$";
local Plane = 200;
local Components = {Rock = 6};