File: Script.c

package info (click to toggle)
openclonk 8.1-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 169,520 kB
  • sloc: cpp: 180,479; ansic: 108,988; xml: 31,371; python: 1,223; php: 767; makefile: 145; sh: 101; javascript: 34
file content (173 lines) | stat: -rw-r--r-- 4,627 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
	Item Spawn
	If the clonk moves through the spawn it automatically gets the item.
	
	@author Maikel, Sven2
*/ 

local Name="$Name$";
local Description="$Description$";

local spawn_id; // Item to be spawned
local team;     // If assigned, spawner can only be used by specific team
local spawn_list; // List keeping track of collected objects to block spawning until used up
local Visibility; // Custom visibility
local spawn_particle; // prepared gfx proplist

/* Interface */

// Definition call: Create an item spawner and set its spawn def
public func Create(id def, int x, int y)
{
	if (this != ItemSpawn)
		return;
	var spawn = CreateObject(ItemSpawn, x, y);
	if (spawn) spawn->SetSpawnObject(def);
	return spawn;
}

// Change object to be spawned by this
public func SetSpawnObject(id def)
{
	spawn_id = def;
	SetGraphics(nil, spawn_id, GFX_Overlay, GFXOV_MODE_Base);
	// Changing the spawn id also resets all collected items to make the spawn available again
	for (var plr in GetPlayers())
	{
		spawn_list[plr] = nil;
		UpdateVisibility(plr);
	}
	return true;
}

// Re-enable spawning for given player
public func Reset(plr)
{
	if (!GetType(plr)) plr = GetPlayers(); else plr = [plr];
	for (var p in plr)
	{
		spawn_list[p] = nil;
		UpdateVisibility(p);
	}
	return true;
}

// If called, items can only be collected by members of this team
public func SetTeam(int new_team)
{
	team = new_team;
	for (var plr in GetPlayers()) UpdateVisibility(plr);
	return true;
}



/*-- Spawn Effect --*/

public func Construction()
{
	spawn_list = [];
	spawn_particle =
		{
			Size = PV_Linear(24, 36),
			Alpha = PV_Linear(0, 255),
			R = PV_Random(200, 255),
			G = PV_Random(200, 255),
			B = PV_Random(200, 255)
		};
	// Initial visibility for all players
	Visibility = [VIS_Select | VIS_God, false,false,false,false];
	for (var plr in GetPlayers()) UpdateVisibility(plr);
	// Timer effect
	AddEffect("Spawn", this, 1, 2, this);
	return true;
}

private func UpdateVisibility(int plr)
{
	// Spawn is visible if the item is currently not collected by the player
	// In case a team is set, it also needs to match
	Visibility[plr+1] = !spawn_list[plr] && (!team || team == GetPlayerTeam(plr));
	return true;
}

private func FxSpawnTimer(object target, proplist effect, int time)
{
	// Produce some particles for the spawn ring.
	if (time % 30 == 0)
		CreateParticle("MagicRing", 0, 0, 0, 0, 60, spawn_particle, 1);
	
	// Update item availability for all active players.
	if (time % 10 == 0)
		for (var plr in GetPlayers()) UpdateVisibility(plr);
	
	// Check for crew members near the item spawn and give the item.
	for (var crew in FindObjects(Find_OCF(OCF_CrewMember), Find_Distance(20)))
	{
		var plr = crew->GetOwner();
		if (!spawn_list[plr] && Visibility[plr+1] && spawn_id)
		{
			if ((!spawn_id->~IsCarryHeavy() && crew->ContentsCount() < crew.MaxContentsCount) || (spawn_id->~IsCarryHeavy() && !crew->IsCarryingHeavy()))
			{
				// Special way to pick up carry heavy objects instantly without animation.
				if (spawn_id->~IsCarryHeavy())
					spawn_list[plr] = crew->CreateCarryHeavyContents(spawn_id);
				else
					spawn_list[plr] = crew->CreateContents(spawn_id);
				UpdateVisibility(plr);
				crew->~Get(spawn_list[plr]); // for sound
			}
		}
	}
	return FX_OK;
}


/* Player/team changes */

public func InitializePlayer(int plr)
{
	// Update visibility and clear spawned item for new player (so we don't need to handle RemovePlayer)
	spawn_list[plr] = nil;
	return UpdateVisibility(plr);
}

public func OnTeamSwitch(int plr, int new_team, int old_team)
{
	// Broadcast on player team switch: Update visibility
	return UpdateVisibility(plr);
}


public func OnClonkDeath(object clonk, int killed_by)
{
	// Reset spawn on clonk death
	// This is odd in multi-clonk rounds with spawn points, but the alternative
	// of not resetting it is probably worse because the spawned item will
	// usually lie around somewhere.
	var plr = clonk->GetOwner();
	if (plr >= 0) Reset(plr);
}


/* Scenario saving */

func SaveScenarioObject(props)
{
	if (!inherited(props, ...)) return false;
	// Visibility is handled by us
	props->Remove("Visibility");
	// Item spawner has its own creation procedure
	if (spawn_id)
	{
		props->RemoveCreation();
		props->Add(SAVEOBJ_Creation, "%i->Create(%i,%d,%d)", GetID() /* to allow overloads */, spawn_id, GetX(), GetY());
	}
	if (team) props->AddCall("Team", this, "SetTeam", team);
	return true;
}


/* Editor props */

local EditorProps = { spawn_id = { Name = "$SpawnID$", EditorHelp = "$SpawnIDHelp$", Priority = 100, Type = "def", Filter = "Collectible", Set = "SetSpawnObject" } };