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
|
055-1,0,0,0|script|_N-Pumpkin|32767
{
//////////////////////////////////
// puppet logic below
set @distance_handler, 1; // silent
set @npc_distance, (1-2); // -1 means attack range
callfunc "PCtoNPCRange";
if (@npc_check) end;
if (Quest_Halloween != 1 || !(gettime(6) == 11 && (gettime(5) >= 4 && gettime(5) <= 30)))
goto L_HeavyPoison;
if (@discover_poisonous_pumpkin == 0)
message strcharinfo(0), "Pumpkin : Yuke, this pumpkin released some ugly poison gas!";
set @discover_poisonous_pumpkin, 1;
misceffect FX_PUMPKIN_EXPLOSION, strcharinfo(0);
heal -15, 0;
sc_start sc_poison, 1, 4;
if (rand(0,100) < 10)
getitem "PumpkinSeeds", 1;
if (countitem("PumpkinSeeds") >= $@halloween_num_seeds)
goto L_EnoughSeeds;
set @mobID, 1063;
callfunc "MobPoints";
goto L_Destroy;
L_EnoughSeeds:
message strcharinfo(0), "Pumpkin : " + $@halloween_num_seeds + " should be enough seeds for Oscar. And this pumpkin gas gets too bad to stand it any longer...";
set Quest_Halloween, 2;
// Reset this to get the message for the "heavy" poison
set @discover_poisonous_pumpkin, 0;
goto L_Destroy;
L_HeavyPoison:
if (@discover_poisonous_pumpkin == 0)
goto L_HeavyPoison0;
if (@discover_poisonous_pumpkin == 1)
goto L_HeavyPoison1;
goto L_HeavyPoison2;
L_HeavyPoison0:
set @discover_poisonous_pumpkin, @discover_poisonous_pumpkin + 1;
message strcharinfo(0), "Pumpkin : Ouch, this pumpkin is totally poisonous! Let's get away from them!";
misceffect FX_PUMPKIN_EXPLOSION, strcharinfo(0);
heal -150,0;
sc_start sc_poison, 1, 60;
goto L_Destroy;
L_HeavyPoison1:
set @discover_poisonous_pumpkin, @discover_poisonous_pumpkin + 1;
message strcharinfo(0), "Pumpkin : This is really awful! I should not touch them!";
misceffect FX_PUMPKIN_EXPLOSION, strcharinfo(0);
heal -350,0;
sc_start sc_poison, 1, 120;
goto L_Destroy;
L_HeavyPoison2:
set @discover_poisonous_pumpkin, @discover_poisonous_pumpkin + 1;
misceffect FX_PUMPKIN_EXPLOSION, strcharinfo(0);
heal -Hp, 0;
goto L_Destroy;
OnAppear:
fakenpcname strnpcinfo(0), strnpcinfo(0), 1063; // set the sprite (implies enablenpc)
end;
L_Destroy:
disablenpc strnpcinfo(0); // makes the npc invisible, unclickable
addnpctimer .death_t, strnpcinfo(0) + "::OnReallyDestroy"; // schedule a respawn
end;
OnReallyDestroy:
set .nodes[.i], get(.nodes[.i], "_N-Pumpkin") - 1, "_N-Pumpkin"; // tell the puppeteer we lost an egg
destroy;
//////////////////////////////////
// puppeteer logic below
S_MakeNode:
set .nID, .nID + 1; // give the node an id
set .@name$, "#_Pkin" + chr(3) + .nID;
goto S_FindXY;
S_FindXY:
set .@x, rand(.x1[.i], .x2[.i]);
set .@y, rand(.y1[.i], .y2[.i]);
if (iscollision(.m$[.i], .@x, .@y) == 1)
goto S_FindXY;
goto S_ReallySpawn;
S_ReallySpawn:
set .@p, puppet(.m$[.i], .@x, .@y, .@name$, 32767); // spawn the node (but not on map, because 32767)
disablenpc .@name$; // make sure it can't be clicked by guessing the being id
set .i, .i, .@p; // tell the puppet what object contains it
set .death_t, rand(.death_t/2, .death_t), .@p; // tell the puppet when to die
set .@timer, if_then_else(.done_initial[.i], rand(.appear_t/2, .appear_t), 0); // timer depends on if first spawn or if respawned after death
addnpctimer .@timer, .@name$+"::OnAppear"; // we spawn the node instantly but it only appears after the timer
if (.nID == 2147483647)
set .nID, 0; // start over if id = 0x7FFFFFFF
return;
S_IterateObjects:
if (.min_nodes[.i] == 0)
set .min_nodes[.i], (.min * min(1, ((.x2[.i] - .x1[.i]) * (.y2[.i] - .y1[.i])) / .divisor));
if (.max_nodes[.i] == 0)
set .max_nodes[.i], (.max * max(1, ((.x2[.i] - .x1[.i]) * (.y2[.i] - .y1[.i])) / .divisor));
if (.nodes[.i] >= .max_nodes[.i])
goto S_NextObject;
set .nodes[.i], .nodes[.i] + 1;
callsub S_MakeNode;
if (.nodes[.i] < if_then_else(.done_initial[.i], .min_nodes[.i], .max_nodes[.i]))
goto S_IterateObjects;
goto S_NextObject;
S_NextObject:
set .done_initial[.i], 1;
if (.i >= (.count - 1))
goto S_Return;
set .i, .i + 1; // object iterator++
goto S_IterateObjects;
S_Return:
return;
OnHeartbeat:
set .i, 0; // object iterator
freeloop 1;
callsub S_IterateObjects;
freeloop 0;
addnpctimer .spawn_t, strnpcinfo(0) + "::OnHeartbeat"; // heartbeat
end;
OnMaybeStart:
if (.x1[1] == 0)
end;
set .min, 0; // relative min number of nodes per object => (min * (((x2 - x1) * (y2 - y1)) / divisor))
set .max, 5; // relative max number of nodes per object => (max * (((x2 - x1) * (y2 - y1)) / divisor))
set .divisor, 32; // see .min & .max ^
set .count, getarraysize(.x1); // number of nodes objects in TSX
set .spawn_t, 18000; // heartbeat rate
set .death_t, 1000; // rand(timer/2, timer) before a node triggers respawn after death
set .appear_t, 40000; // rand(timer/2, timer) before a node becomes visible after spawn
if (.started)
end;
set .started, 1;
addnpctimer 10000, strnpcinfo(0)+"::OnHeartbeat"; // first heartbeat
end;
}
|