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