1 /**
2 	Locomotive Highway
3 	Construct and protect the locomotive highway.
4 
5 	@author Maikel
6 */
7 
8 
9 #include Library_Goal
10 #include Library_SwitchTarget
11 
12 
13 /*-- Control --*/
14 
15 // Reaction to operation by a switch.
OnSetInputSignal(object operator,object switch,bool right)16 public func OnSetInputSignal(object operator, object switch, bool right)
17 {
18 	if (!right)
19 	{
20 		if (!GetEffect("FxRunLocomotives", this) && !FindObject(Find_ID(Locomotive)))
21 			CreateEffect(FxRunLocomotives, 100, 36, this);
22 		switch->ControlSwitchDir(nil, -1);
23 	}
24 	_inherited(operator, switch, right, ...);
25 }
26 
27 local FxRunLocomotives = new Effect
28 {
func(object goal)29 	Construction = func(object goal)
30 	{
31 		this.goal = goal;
32 		this.Interval = 36;
33 		this.train_int = 15;
34 		this.train_start = 1;
35 		this.goal->SetPassed(0);
36 		return FX_OK;
37 	},
38 	Timer = func(int time)
39 	{
40 		if (time > this.Interval * this.train_int * Target.LocomotiveGoal)
41 			return FX_Execute_Kill;
42 		// Launch a locomotive.
43 		if ((time / this.Interval) % this.train_int == this.train_start)
44 		{
45 			var loco = CreateObjectAbove(Locomotive, 12, LandscapeHeight() / 2 - 3);
46 			loco->SetEntrance(false);
47 			loco.IsContainer = Goal_LocomotiveHighway.FxRunLocomotives.NoContainer;
48 			loco.HasInteractionMenu = Goal_LocomotiveHighway.FxRunLocomotives.NoInteractions;
49 			loco->SetDir(DIR_Right);
50 			loco->CreateContents(Coal, 100);
51 			loco.LiquidCapacity = 100000;
52 			loco->PutLiquid(Water, 100000);
53 			loco->ContainedRight();
54 			loco->CreateEffect(Target.FxCheckLocomotive, 100, 2, this.goal);
55 		}
56 		return FX_OK;
57 	},
58 	NoContainer = func()
59 	{
60 		return false;
61 	},
62 	NoInteractions = func()
63 	{
64 		return false;
65 	}
66 };
67 
68 local FxCheckLocomotive = new Effect
69 {
func(object goal)70 	Construction = func(object goal)
71 	{
72 		this.goal = goal;
73 		// The allowed time means that no obstacles must be in the way.
74 		// The train moves roughly at a pace of 1.3-1.4 pixels per frame.
75 		this.time_allowed = 4 * LandscapeWidth() / 5;
76 		this.Interval = 2;
77 		return FX_OK;
78 	},
79 	Timer = func(int time)
80 	{
81 		if (Target->GetX() > LandscapeWidth() - 14)
82 		{
83 			if (time <= this.time_allowed)
84 				this.goal->DoPassed(1);
85 			Target->RemoveObject();
86 			return FX_Execute_Kill;
87 		}
88 		if (time > this.time_allowed)
89 		{
90 			Target->FadeOut(18, true);
91 			return FX_Execute_Kill;
92 		}
93 		return FX_OK;
94 	}
95 };
96 
97 
98 /*-- Goal interface --*/
99 
100 local nr_passed = 0;
101 
SetPassed(int to_passed)102 public func SetPassed(int to_passed)
103 {
104 	nr_passed = to_passed;
105 	return;
106 }
107 
GetPassed()108 public func GetPassed() { return nr_passed; }
109 
DoPassed(int add_passed)110 public func DoPassed(int add_passed)
111 {
112 	SetPassed(GetPassed() + add_passed);
113 	return;
114 }
115 
IsFulfilled()116 public func IsFulfilled()
117 {
118 	return nr_passed >= this.LocomotiveGoal;
119 }
120 
GetDescription(int plr)121 public func GetDescription(int plr)
122 {
123 	var message;
124 	if (IsFulfilled())
125 	{
126 		message = "$MsgGoalFulfilled$";
127 	}
128 	else
129 	{
130 		if (GetEffect("FxRunLocomotives", this) || FindObject(Find_ID(Locomotive)))
131 			message = Format("$MsgGoalRunning$", GetPassed(), this.LocomotiveGoal);
132 		else
133 			message = "$MsgGoalUnfulfilled$";
134 	}
135 	return message;
136 }
137 
138 // Shows or hides a message window with information.
Activate(int plr)139 public func Activate(int plr)
140 {
141 	// If goal message open -> hide it.
142 	if (GetEffect("GoalMessage", this))
143 	{
144 		CustomMessage("", nil, plr, nil, nil, nil, nil, nil, MSG_HCenter);
145 		RemoveEffect("GoalMessage", this);
146 		return;
147 	}
148 	// Otherwise open a new message.
149 	AddEffect("GoalMessage", this, 100, 0, this);
150 	var message;
151 	if (IsFulfilled())
152 	{
153 		message = "@$MsgGoalFulfilled$";
154 	}
155 	else
156 	{
157 		if (GetEffect("FxRunLocomotives", this) || FindObject(Find_ID(Locomotive)))
158 			message = Format("@$MsgGoalRunning$", GetPassed(), this.LocomotiveGoal);
159 		else
160 			message = "@$MsgGoalUnfulfilled$";
161 	}
162 	CustomMessage(message, nil, plr, 0, 16 + 64, 0xffffff, GUI_MenuDeco, this, MSG_HCenter);
163 	return;
164 }
165 
FxGoalMessageStart()166 protected func FxGoalMessageStart() {}
167 
168 
169 /*-- Proplist --*/
170 
171 local Name = "$Name$";
172 local LocomotiveGoal = 12;
173