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
|
/**
Insect Swarm Library
Superimpose to any (flying) insect to create an insect swarm.
@author Clonkonaut
--*/
#include Library_Insect
// Places amount swarms with swarm_members individuals each
public func Place(int amount, int swarm_members, proplist area)
{
// No calls to objects, only definitions
if (GetType(this) == C4V_C4Object) return;
if (!swarm_members)
swarm_members = lib_swarm_standard;
for (var insect in _inherited(amount, area))
insect->CreateSwarm(swarm_members - 1); // -1 because one insect already exists
}
/** Call something for every swarm member
*/
public func SwarmCall(string fn, par1, par2, par3, par4, par5, par6, par7, par8, par9)
{
if (!lib_swarm_helper) return;
lib_swarm_helper->SwarmCall(fn, par1, par2, par3, par4, par5, par6, par7, par8, par9);
}
/** Standard swarm size (utilised in Place()). Default 10.
*/
local lib_swarm_standard = 10;
/** Maximum distance one individual can be away from another. Default 10 pixels.
*/
local lib_swarm_density = 10;
// The managing object (see SwarmHelper.ocd)
local lib_swarm_helper;
// The next insect that gets promoted to swarm master when the swarm master dies
local lib_swarm_nextinline;
// The previous insect that gets promoted to swarm master before this one
local lib_swarm_previnline;
/** Promotes this to swarm master and will create amount minions
*/
public func CreateSwarm(int amount)
{
if (amount <= 0) return;
// Create a swarm helper
lib_swarm_helper = CreateObject(Library_Swarm_Helper, AbsX(0), AbsY(0), NO_OWNER);
lib_swarm_helper->SetMaster(this);
lib_swarm_helper->SetSwarmCount(amount);
var last_created = this, insect;
while (amount)
{
insect = CreateObject(GetID(), 0, 0, GetOwner());
insect->SetPreviousInLine(last_created);
insect->SetSwarmHelper(lib_swarm_helper);
insect->SetCommand("None");
last_created->SetNextInLine(insect);
last_created = insect;
amount--;
}
return lib_swarm_helper;
}
public func SetNextInLine(object next)
{
lib_swarm_nextinline = next;
}
public func SetPreviousInLine(object next)
{
lib_swarm_previnline = next;
}
public func SetSwarmHelper(object helper)
{
lib_swarm_helper = helper;
lib_swarm_helper->AddSwarmMember(this);
}
// Swarm insect need randomized activities to not look odd
private func Initialize()
{
AddTimer("Activity", 10 + Random(25));
SetComDir(COMD_None);
}
// On death or destruction we need to update the line
private func Death()
{
// Death of the master
if (lib_swarm_helper)
if (lib_swarm_helper->GetMaster() == this)
lib_swarm_helper->MakeNewMaster(lib_swarm_nextinline);
// Death of a slave
if (lib_swarm_previnline && lib_swarm_nextinline)
{
lib_swarm_nextinline->SetPreviousInLine(lib_swarm_previnline);
lib_swarm_previnline->SetNextInLine(lib_swarm_nextinline);
}
PurgeLine(); // Don't do everything twice in case Destruction() follows
_inherited(...);
}
private func Destruction()
{
// Destruction of the master
if (lib_swarm_helper)
if (lib_swarm_helper->GetMaster() == this)
lib_swarm_helper->MakeNewMaster(lib_swarm_nextinline);
// Destruction of a slave
if(lib_swarm_previnline && lib_swarm_nextinline)
{
lib_swarm_nextinline->SetPreviousInLine(lib_swarm_previnline);
lib_swarm_previnline->SetNextInLine(lib_swarm_nextinline);
}
}
private func PurgeLine()
{
lib_swarm_nextinline = nil;
lib_swarm_previnline = nil;
}
private func MoveToTarget()
{
if (!lib_swarm_helper || (lib_swarm_helper->GetMaster() == this))
return _inherited(...);
var x, y;
// Follow previous in line
if (lib_swarm_previnline && Random(3))
{
x = lib_swarm_previnline->GetX();
y = lib_swarm_previnline->GetY();
}
else // Go wild and stay around the master!
{
var point = {};
lib_swarm_helper->GetSwarmCenter(point);
x = point.x;
y = point.y;
}
x = BoundBy(x + Random(lib_swarm_density * 2) - lib_swarm_density, 10, LandscapeWidth() - 10);
y = BoundBy(y + Random(lib_swarm_density * 2) - lib_swarm_density, 10, LandscapeHeight() - 10);
// Only move if there is no solid or liquid at this coordinate, otherwise just wait for next activity update.
if (GBackSemiSolid(x - GetX(), y - GetY()))
return;
SetCommand("MoveTo", nil, x, y, nil, true);
AppendCommand("Call", this, nil, nil, nil, nil, "MissionComplete");
return;
}
/* Saving */
public func SaveScenarioObject(proplist props)
{
if (!inherited(props, ...)) return false;
// Do not save swarms - this will be done by the swarm helper instad
return !lib_swarm_helper;
}
|