forked from Mirrors/openclonk
262 lines
5.3 KiB
C
262 lines
5.3 KiB
C
/*
|
|
Hatch
|
|
|
|
@authors: Clonkonaut, Ringwaul (Graphics)
|
|
*/
|
|
|
|
#include Library_Structure
|
|
|
|
local opened = false;
|
|
|
|
/*-- Engine Callbacks --*/
|
|
|
|
func Construction()
|
|
{
|
|
SetProperty("MeshTransformation", Trans_Mul(Trans_Translate(0,-10000), Trans_Rotate(-10,0,1,0), Trans_Rotate(-8,1,0,0)));
|
|
SetCategory(C4D_StaticBack);
|
|
|
|
return _inherited(...);
|
|
}
|
|
|
|
func Initialize()
|
|
{
|
|
// If the hatch has not been properly combined with a basement, we might want to correct that
|
|
if (!GetBasement())
|
|
{
|
|
var basements = FindObjects(Find_AtRect(-1,0, 2,4), Find_Func("IsBasement"), Sort_Distance());
|
|
for (var basement in basements)
|
|
{
|
|
if (!basement->GetParent() && basement->GetWidth() == 40)
|
|
{
|
|
SetPosition(basement->GetX(), basement->GetY()-2);
|
|
basement->SetParent(this);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return _inherited(...);
|
|
}
|
|
|
|
/*-- Callbacks --*/
|
|
|
|
public func IsHammerBuildable() { return true; }
|
|
|
|
public func DoConstructionEffects(object construction_site)
|
|
{
|
|
// The hatch sets itself a bit lower after it has been placed with the construction previewer
|
|
SetPosition(GetX(), GetY()+4);
|
|
return false;
|
|
}
|
|
|
|
public func NoConstructionFlip() { return true; }
|
|
|
|
public func ConstructionCombineWith() { return "IsBasement"; }
|
|
|
|
public func ConstructionCombineDirection(object other) { return CONSTRUCTION_STICK_Top; }
|
|
|
|
public func CombineWith(object stick_to)
|
|
{
|
|
if (stick_to && stick_to->~IsBasement())
|
|
stick_to->SetParent(this);
|
|
|
|
SetPosition(GetX(), GetY()+1);
|
|
}
|
|
|
|
/*-- Library overloads --*/
|
|
|
|
func MoveOutOfSolidMask()
|
|
{
|
|
// Find all objects inside the solid mask which are stuck.
|
|
var lying_around = FindObjects(Find_Or(Find_Category(C4D_Vehicle), Find_Category(C4D_Object), Find_Category(C4D_Living)), Find_InRect(-13, -2, 26, 4), Find_NoContainer());
|
|
// Move up these objects.
|
|
for (var obj in lying_around)
|
|
{
|
|
var x = obj->GetX();
|
|
var y = obj->GetY();
|
|
var delta_y = 0;
|
|
var max_delta = obj->GetObjHeight();
|
|
// Move up object until it is not stuck any more.
|
|
while (obj->Stuck() || obj->GetContact(-1, CNAT_Bottom))
|
|
{
|
|
// Only move up the object by at most its height plus the basements height.
|
|
if (delta_y > max_delta)
|
|
{
|
|
obj->SetPosition(x, y);
|
|
break;
|
|
}
|
|
delta_y++;
|
|
obj->SetPosition(x, y - delta_y);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*-- Basement --*/
|
|
|
|
public func GetBasementWidth()
|
|
{
|
|
return 40;
|
|
}
|
|
|
|
public func SetBasement(object to_basement)
|
|
{
|
|
_inherited(to_basement);
|
|
|
|
if (!to_basement) return;
|
|
|
|
to_basement->ChangeDef(HatchBasement);
|
|
}
|
|
|
|
public func GetBasementOffset() { return [0, -15]; }
|
|
|
|
/*-- Interaction --*/
|
|
|
|
public func IsInteractable(object clonk)
|
|
{
|
|
if (GetCon() < 100)
|
|
return false;
|
|
if (opened && FindClonkInHatchArea())
|
|
return false;
|
|
|
|
if (Hostile(clonk->GetOwner(), GetOwner()))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public func GetInteractionMetaInfo(object clonk)
|
|
{
|
|
if (!ActIdle())
|
|
return { Description = "$Close$", IconName = nil, IconID = Icon_Exit, Selected = false };
|
|
return { Description = "$Open$", IconName = nil, IconID = Icon_Enter, Selected = false };
|
|
}
|
|
|
|
public func Interact(object clonk)
|
|
{
|
|
if (ActIdle())
|
|
return DoOpen();
|
|
if (GetAction() == "Open")
|
|
return DoClose();
|
|
return false;
|
|
}
|
|
|
|
/*-- Open/Close --*/
|
|
|
|
public func DoOpen()
|
|
{
|
|
SetAction("Open");
|
|
Sound("Structures::DoorOpen?");
|
|
return true;
|
|
}
|
|
|
|
public func DoClose()
|
|
{
|
|
if (opened)
|
|
{
|
|
if (FindClonkInHatchArea())
|
|
return false;
|
|
SetAction("Close");
|
|
Sound("Structures::DoorClose?");
|
|
opened = false;
|
|
return true;
|
|
}
|
|
if (GetAction() == "Open")
|
|
{
|
|
var phase = 2 - GetPhase();
|
|
SetAction("Close");
|
|
Sound("Structures::DoorClose?");
|
|
SetPhase(phase);
|
|
return true;
|
|
}
|
|
SetAction("Close");
|
|
Sound("Structures::DoorClose?");
|
|
return true;
|
|
}
|
|
|
|
func FindClonkInHatchArea()
|
|
{
|
|
return FindObject(Find_InRect(-16, -12, 32, 24), Find_OCF(OCF_CrewMember), Find_OCF(OCF_Alive), Find_AnyLayer(), Find_NoContainer());
|
|
}
|
|
|
|
func ChangeSolidMask()
|
|
{
|
|
if (opened)
|
|
return;
|
|
if (GetAction() == "Close") // Upon closing, the solid mask must reappear instantaneously
|
|
// to prevent clonks from getting stuck
|
|
return SetSolidMask(0,0, 26,4, 0,11);
|
|
|
|
var phase = GetPhase();
|
|
var width = 26 - 8*phase;
|
|
|
|
if (phase == 3) {
|
|
ClosingTimer();
|
|
width -= 2;
|
|
}
|
|
|
|
SetSolidMask(0,0, width,4, 0,11);
|
|
}
|
|
|
|
func ClosingTimer()
|
|
{
|
|
opened = true;
|
|
|
|
ScheduleCall(this, "CheckForClose", 15);
|
|
}
|
|
|
|
func CheckForClose()
|
|
{
|
|
if (GetAction() == "Close" || ActIdle())
|
|
return;
|
|
|
|
if (!FindClonkInHatchArea())
|
|
return ScheduleCall(this, "CloseForReal", 25);
|
|
|
|
ScheduleCall(this, "CheckForClose", 5);
|
|
}
|
|
|
|
func CloseForReal()
|
|
{
|
|
// One final check that the hatch is clear
|
|
if (FindClonkInHatchArea())
|
|
return ScheduleCall(this, "CheckForClose", 5);
|
|
|
|
DoClose();
|
|
}
|
|
|
|
/*-- Display --*/
|
|
|
|
func Definition(def)
|
|
{
|
|
SetProperty("PictureTransformation", Trans_Mul(Trans_Translate(0,-3000,-5000), Trans_Rotate(-30,1,0,0), Trans_Rotate(30,0,1,0), Trans_Translate(1000,1,0)), def);
|
|
return _inherited(def);
|
|
}
|
|
|
|
/*-- Properties --*/
|
|
|
|
local ActMap = {
|
|
Open = {
|
|
Prototype = Action,
|
|
Name = "Open",
|
|
Length = 3,
|
|
Delay = 5,
|
|
Animation = "Open",
|
|
NextAction = "Hold",
|
|
PhaseCall = "ChangeSolidMask"
|
|
},
|
|
Close = {
|
|
Prototype = Action,
|
|
Name = "Close",
|
|
Length = 3,
|
|
Delay = 5,
|
|
Animation = "Close",
|
|
NextAction = "Idle",
|
|
PhaseCall = "ChangeSolidMask"
|
|
},
|
|
};
|
|
|
|
local Name = "$Name$";
|
|
local Description = "$Description$";
|
|
local BlastIncinerate = 100;
|
|
local HitPoints = 70;
|
|
local Components = {Wood = 2};
|