1 /**
2 	Stone Door
3 	A door which can be used in scenarios with lots of bricks.
4 
5 	@authors Ringwaul, Maikel
6 */
7 
8 #include Library_SwitchTarget
9 
Initialize()10 protected func Initialize()
11 {
12 	SetAction("Door");
13 	SetComDir(COMD_Stop);
14 	return;
15 }
16 
17 /*-- Movement --*/
18 
OpenDoor()19 public func OpenDoor()
20 {
21 	ForceDigFree();
22 	SetComDir(COMD_Up);
23 	Sound("Structures::StoneGate::GateMove");
24 	return;
25 }
26 
CloseDoor()27 public func CloseDoor()
28 {
29 	ForceDigFree();
30 	SetComDir(COMD_Down);
31 	Sound("Structures::StoneGate::GateMove");
32 	return;
33 }
34 
IsOpen()35 private func IsOpen()
36 {
37 	if (GetContact(-1) & CNAT_Top)
38 	 	return true;
39 	return false;
40 }
41 
IsClosed()42 private func IsClosed()
43 {
44 	if (GetContact(-1) & CNAT_Bottom)
45 	 	return true;
46 	return false;
47 }
48 
Hit()49 protected func Hit()
50 {
51 	Sound("Structures::StoneGate::GateHit");
52 	return;
53 }
54 
55 // Digs away earth behind the door. Needs to temporarily disable the solid mask, though.
ForceDigFree()56 private func ForceDigFree()
57 {
58 	SetSolidMask();
59 	DigFreeRect(GetX() - 4, GetY() - 20, 8, 40, true);
60 	SetSolidMask(0, 0, 8, 40);
61 }
62 
63 /*-- Switch control --*/
64 
65 // Reaction to operation by a switch: if open_door is true the door opens, otherwise it closes
OnSetInputSignal(object operator,object switch,bool open_door)66 public func OnSetInputSignal(object operator, object switch, bool open_door)
67 {
68 	if (open_door)
69 	{
70 		OpenDoor();
71 	}
72 	else
73 	{
74 		CloseDoor();
75 	}
76 
77 	_inherited(operator, switch, open_door, ...);
78 }
79 
80 /*-- Automatic movement --*/
81 
82 // Overrules owner control and only let's the team through.
SetAutoControl(int team)83 public func SetAutoControl(int team)
84 {
85 	var effect = AddEffect("AutoControl", this, 100, 3, this);
86 	effect.Team = team;
87 	return;
88 }
89 
FxAutoControlTimer(object target,effect,int time)90 protected func FxAutoControlTimer(object target, effect, int time)
91 {
92 	var d = 0;
93 	if (IsOpen())
94 		d = 30;
95 	var owner = GetOwner();
96 	var team = effect.Team;
97 	var open_door = false;
98 	// Team control
99 	if (team != nil)
100 		for (var clonk in FindObjects(Find_OCF(OCF_CrewMember), Find_InRect(-50, d - 30, 100, 60)))
101 		{
102 			var plr = clonk->GetOwner();
103 			var plr_team = GetPlayerTeam(plr);
104 			if (team == 0 || plr_team == team)
105 				open_door = true;
106 		}
107 	// Player control
108 	else
109 		if (FindObject(Find_OCF(OCF_CrewMember), Find_InRect(-50, d - 30, 100, 60), Find_Allied(owner)))
110 			open_door = true;
111 
112 	// Keep door closed if hostile?
113 	// TODO?
114 
115 	if (open_door && IsClosed())
116 		OpenDoor();
117 	if (!open_door && IsOpen())
118 		CloseDoor();
119 
120 	return 1;
121 }
122 
FxAutoControlSaveScen(obj,fx,props)123 func FxAutoControlSaveScen(obj, fx, props)
124 {
125 	props->AddCall("AutoControl", obj, "SetAutoControl", fx.team);
126 	return true;
127 }
128 
129 /*-- Destruction --*/
130 
GetStrength()131 private func GetStrength() { return 180; }
132 
Damage()133 protected func Damage()
134 {
135 	// Destroy if damage above strength.
136 	if (GetDamage() > GetStrength())
137 	{
138 		var particles =
139 		{
140 			Size = PV_KeyFrames(0, 0, 0, 100, PV_Random(3, 5), 1000, 3),
141 			R = PV_Random(230, 250),
142 			G = PV_Random(210, 230),
143 			B = PV_Random(190, 210),
144 			Alpha = PV_Linear(255, 0),
145 			ForceY = PV_Gravity(100),
146 			CollisionVertex = 0
147 		};
148 		CreateParticle("SmokeDirty", PV_Random(-4, 4), PV_Random(-18, 18), PV_Random(-10, 10), PV_Random(-10, 10), PV_Random(10, 60), particles, 300);
149 		CastObjects(Rock, 5, 20);
150 		return RemoveObject();
151 	}
152 	// Change appearance.
153 	DoGraphics();
154 	return;
155 }
156 
DoGraphics()157 private func DoGraphics()
158 {
159 	// Change appearance according to damage and strength.
160 	if (GetDamage() > 3 * GetStrength() / 4)
161 		SetGraphics("Cracked3");
162 	else if (GetDamage() > GetStrength() / 2)
163 		SetGraphics("Cracked2");
164 	else if (GetDamage() > GetStrength() / 4)
165 		SetGraphics("Cracked1");
166 	else
167 		SetGraphics("");
168 	return;
169 }
170 
GetFloorOffset()171 public func GetFloorOffset()
172 {
173 	// Searches downwards from the lowest vertex to the floor
174 	var y_off;
175 	for (y_off=0; !GBackSolid(0, 20+y_off); ++y_off)
176 		if (y_off > 20) break; // max range
177 	return y_off;
178 }
179 
180 
181 /* Editor */
182 
183 local EditorActions = {
184 	OpenDoor = { Name = "$DoorUp$", Command = "OpenDoor()" },
185 	CloseDoor = { Name = "$DoorDown$", Command = "CloseDoor()" }
186 };
187 
Definition(def,...)188 public func Definition(def, ...)
189 {
190 	UserAction->AddEvaluator("Action", "Structure", "$DoorUp$", "$DoorUpDesc$", "open_door", [def, def.EvalAct_OpenDoor], { }, UserAction->GetObjectEvaluator("IsDoor", "$Door$", "$DoorTargetHelp$"), "Door");
191 	UserAction->AddEvaluator("Action", "Structure", "$DoorDown$", "$DoorDownDesc$", "close_door", [def, def.EvalAct_CloseDoor], { }, UserAction->GetObjectEvaluator("IsDoor", "$Door$", "$DoorTargetHelp$"), "Door");
192 	return _inherited(def, ...);
193 }
194 
EvalAct_OpenDoor(props,context)195 private func EvalAct_OpenDoor(props, context)
196 {
197 	var door = UserAction->EvaluateValue("Object", props.Door, context);
198 	if (door) door->~OpenDoor();
199 }
200 
EvalAct_CloseDoor(props,context)201 private func EvalAct_CloseDoor(props, context)
202 {
203 	var door = UserAction->EvaluateValue("Object", props.Door, context);
204 	if (door) door->~CloseDoor();
205 }
206 
207 /* Properties */
208 
IsDoor()209 public func IsDoor() { return true; }
210 
211 local ActMap = {
212 	Door = {
213 		Prototype = Action,
214 		Name = "Door",
215 		Procedure = DFA_FLOAT,
216 		Speed = 150,
217 		Accel = 12,
218 		Decel = 12,
219 		Length = 1,
220 		Delay = 1,
221 		X = 0,
222 		Y = 0,
223 		Wdt = 8,
224 		Hgt = 40,
225 		NextAction = "Door",
226 	},
227 };
228 
229 local Name = "$Name$";
230 local Plane = 200;
231 local Components = {Rock = 6};
232 
233 
234