openclonk/planet/Objects.ocd/Items.ocd/Tools.ocd/Torch.ocd/Script.c

273 lines
5.8 KiB
C

/**
Torch
Can be either held or attached to tunnel material to illuminate dark caves.
@author Pyrit, Maikel
--*/
// State of the torch: Normal (contained, lying around), in hand or attached.
local state;
local TRCH_Normal = 0;
local TRCH_InHand = 1;
local TRCH_Attached = 2;
local TRCH_Fixed = 3;
local transform; // for debugging
/*-- Engine Callbacks --*/
func Initialize()
{
SetState(TRCH_Normal);
SetMeshMaterial("Torch");
}
func Hit()
{
Sound("Hits::Materials::Wood::WoodHit?");
}
public func Selection(object container)
{
if (container && container->~IsClonk())
{
SetState(TRCH_InHand);
}
return _inherited(container, ...);
}
public func Deselection(object container)
{
if (container->~IsClonk())
{
SetState(TRCH_Normal);
}
return _inherited(container, ...);
}
public func SaveScenarioObject(proplist props, ...)
{
if (!_inherited(props, ...)) return false;
props->AddCall("SetState", this, "SetState", state);
if (state == TRCH_Attached || state == TRCH_Fixed)
{
props->AddCall("Attach", this, "AttachToWall", state == TRCH_Fixed);
props->Remove("Category");
props->Remove("Plane");
}
return true;
}
/*-- Callbacks --*/
// Returns whether the torch currently is a source of light.
public func IsLightSource()
{
return !!GetEffect("IntBurning", this);
}
public func IsInteractable(object clonk)
{
return state == TRCH_Attached;
}
public func GetInteractionMetaInfo(object clonk)
{
return { Description = "$MsgTorchDetach$", IconName = nil, IconID = nil, Selected = false };
}
/*-- Usage --*/
public func RejectUse(object clonk)
{
return !clonk->HasHandAction();
}
public func ControlUse(object clonk)
{
// Attach the torch if the clonk stands in front of tunnel material.
if (GetMaterial() == Material("Tunnel"))
{
AttachToWall();
return true;
}
// Otherwise log a message about where one can attach torches.
Message("$MsgTorchAttach$");
return true;
}
public func Interact(object clonk)
{
// detach the torch from the wall.
DetachFromWall();
clonk->Collect(this, false, nil, true);
return true;
}
// Attaches the torch to the wall.
public func AttachToWall(bool fixed)
{
// Exit the torch and make it a non-collectible static back, also change its state.
if (Contained()) Exit(0, 3);
SetCategory(C4D_StaticBack);
this.Collectible = false;
SetState(TRCH_Attached);
if (fixed)
SetState(TRCH_Fixed);
// Set plane so that it is in the background.
this.Plane = 1;
// Rotate the head of the torch a little into the screen.
this.MeshTransformation = Trans_Rotate(-20, 1, 0, 0);
return;
}
// Detaches the torch from the wall.
public func DetachFromWall()
{
// Make the torch a collectible object, also change its state.
SetCategory(C4D_Object);
this.Collectible = true;
SetState(TRCH_Normal);
return;
}
// Set the state of the torch.
public func SetState(int to_state)
{
state = to_state;
if (state == TRCH_Normal) Burn(false);
else Burn(true);
return;
}
/*-- Burning Effect --*/
func FxIntBurningStart(object target, effect fx, int temporary)
{
if (temporary)
return 1;
// Starting interval
fx.Interval = 4;
// Fire particle
fx.flame =
{
R = PV_KeyFrames(0, 0, 0, 200, 255, 800, 255, 1000, 255),
G = PV_KeyFrames(0, 0, 0, 200, 210, 800, 70, 1000, 70),
B = PV_KeyFrames(0, 0, 255, 200, 100, 800, 0, 1000, 0),
Alpha = PV_KeyFrames(1000, 0, 0, 10, 255, 500, 255, 1000, 0),
Size = PV_Linear(PV_Random(2, 3), PV_Random(4, 5)),
Stretch = 1000,
Phase = PV_Random(0, 4),
Rotation = PV_Random(0, 359),
DampingX = 900,
DampingY = 1000,
BlitMode = GFX_BLIT_Additive,
CollisionVertex = 0,
OnCollision = PC_Die()
};
fx.smoke =
{
Prototype = Particles_Smoke(),
Size = PV_Linear(PV_Random(2, 3), PV_Random(3, 5))
};
// Set the light range for this torch.
SetLightRange(80, 60);
SetLightColor(FIRE_LIGHT_COLOR);
return 1;
}
func FxIntBurningTimer (object target, effect fx, int time)
{
// If the torched is attached or fixed it should emit some fire and smoke particles.
if (state != TRCH_Normal)
{
if(Contained() && (Contained()->~InLiquid() || !Contained()->~HasHandAction())) return -1;
var pos = GetParticleOffset();
// Fire effects.
CreateParticle("FireSharp", PV_Random(-1 + pos[0], 2 + pos[0]), PV_Random(0 + pos[1], -3 + pos[1]), PV_Random(-2, 2), PV_Random(-3, -5), 10 + Random(3), fx.flame, 12);
// Smoke effects.
CreateParticle("Smoke", PV_Random(-1 + pos[0], 2 + pos[0]), PV_Random(-7, -9), PV_Random(-2, 2), PV_Random(-2, 2), 24 + Random(12), fx.smoke, 4);
// Interval jitter
if (!Random(10)) fx.Interval = 3+Random(3);
}
return 1;
}
func FxIntBurningStop(object target, proplist effect, int reason, bool temporary)
{
if (temporary)
return 1;
// Remove the light from this torch.
SetLightRange(0);
return 1;
}
private func Burn(bool burn)
{
if (burn)
{
if (!GetEffect("IntBurning", this))
{
AddEffect("IntBurning", this, 100, 4, this);
}
}
else
{
if (GetEffect("IntBurning", this))
{
RemoveEffect("IntBurning", this);
}
}
}
/*-- Production --*/
public func IsTool() { return true; }
public func IsToolProduct() { return true; }
/*-- Display --*/
public func GetCarryMode(object clonk)
{
if (clonk && !clonk->~HasHandAction())
{
Burn(false);
return CARRY_Back;
}
else
{
Burn(true);
return CARRY_Spear;
}
}
public func GetCarryTransform(object clonk, int sec, bool nohand)
{
return Trans_Rotate(90, 0, 0, 1);
}
private func GetParticleOffset()
{
if(state != TRCH_InHand || !Contained() || !(Contained() && Contained()->~IsClonk())) return [0,0];
// Special handling for clonks
var off = [-4, -6];
if(Contained()->GetDir() == DIR_Right) off[0] = 4;
return off;
}
func Definition(def)
{
SetProperty("PictureTransformation", Trans_Mul(Trans_Translate(2500, -1500, 0), Trans_Rotate(-30, 0, 0, 1)), def);
}
/*-- Properties --*/
local Name = "$Name$";
local Description = "$Description$";
local Collectible = true;
local Components = {Wood = 1, Coal = 1};