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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
|
// TMW-2 Script
// Author:
// Jesusalva
// Description:
// GM Bot for the Monster King.
// VARIABLES
// $GAME_STORYLINE - Current Storyline status
// $@MK - Monster King Game ID
// $@MK_SCENE - Current event being handled by the Monster King
// $MK_TEMPVAR - Temporary Variable
// $@MK_THROTTLE - Event Throttler
//
// Storyline statuses:
// 0 - The Monster King is inactive (leading sieges to Hurnscald and Nivalis)
// 1 - The Monster King is known by players and is giving them a month break
// 2 - The Monster King is currently sieging towns at random
// 3 - The Monster King is preparing to perfom the Rite and Lightbringer seeks
// a wielder
// 4 - The Rite is CONCLUDED. Players must walk to MK evil lair and fight.
// 5 - The Monster King is dead. Or something. Depends on players.
//
// $MK_TEMPVAR meaning depends on GAME STORYLINE
// GS 0
// Ignored
// GS 1
// Tracks the day since 1970 when the town was cleared. A month break.
// GS 2
// Player score (1pt per Lieutenant, 10pts per Colonel)
// Affects the end of Game Story 2 and begin of Game Story 3
// Because we must wait players...
// GS 3
// Number of successful Fortress Town breaches
// GS 4
// Inheirs stage 3
000-0,0,0,0 script Monster King NPC_HIDDEN,{
OnSlaveDie:
end;
OnBourneAgain:
// Reset aggro
$@MK_AGGRO=0;
if (playerattached()) {
if (!FLAGS & FLAG_MKFIRSTBLOOD) {
channelmes("#world", strcharinfo(0)+" did an act worth of notice.");
FLAGS = FLAGS | FLAG_MKFIRSTBLOOD;
dispbottom l("Oh well, this sucks, but that was only an illusion.");
dispbottom l("The real Monster King is probably on his fortress. It'll take more than that to take him down.");
} else {
dispbottom l("While it is utterly pointless, you once again vanish the Monster King's illusion.");
}
if ($REBIRTH_WINNER$ == "" && TOP3AVERAGELVL() < 100)
getexp min(641500, BaseLevel**3), 0;
else if (!$FIRESOFSTEAM)
Mobpt+=max(13500, rand2(10000, BaseLevel*90));
else
Mobpt+=(max(13500, rand2(10000, BaseLevel*90)) * 2 / 3);
Mobpt = Mobpt + 165;
//$MOST_HEROIC$=strcharinfo(0);
specialeffect(FX_FANFARE, AREA, getcharid(3));
}
// We need to start over
.bar=true;
OnInit:
$@MK=monster("boss", 45, 45, "The Monster King", MonsterKing, 1, "Monster King::OnBourneAgain");
if (!.bar) {
// Variables which other NPCs must take in account
$@MK_AGGRO=0;
$@MK_SCENE=0;
} else {
.bar=false;
}
// Variables only for this NPC
.users=getusers(1);
.nearby=getusers(8);
.mp$="boss";
.aid=2000000;
.cid=150002;
// Constants
// This script is superseded, so no initialization is required.
// (Sieges and Personal Sieges no longer happen after Monster King dies)
if ($GAME_STORYLINE >= 5)
end;
// We should jump straight to loop (it runs every 90 seconds)
OnTimer90000:
// Regenerate some data, and kill spurious mobs
.users=getusers(1);
if (mobcount(.mp$, "Monster King::OnSlaveDie")) {
announce ("Monster King: Noobs, you are all a bunch of noobs!"), bc_map|bc_npc;
killmonster(.mp$, "Monster King::OnSlaveDie");
}
// We are on an event, so skip this loop
if ($@MK_SCENE || $@GM_EVENT) {
initnpctimer;
end;
}
// Check if MK is still alive
if (getunittype($@MK) < 0) {
consolebug("Monster King GID %d is not a valid unit type!", $@MK);
sleep(300); // Wait 5 minutes for the respawn
consolewarn("Forcefully respawning Monster King now (GID was invalid)");
.bar=true;
goto OnInit;
}
// The Monster King is online. This loop is not needed
if (isloggedin(.aid, .cid)) {
if (!$@MK_SCENE)
unitwarp($@MK, "boss", 45, 45);
else
rodex_sendmail(.cid, "MKBot", "Running Event", "An event is currently running by the MK Bot. Please logout and suppress it.");
initnpctimer;
}
// Raise aggro (1 pt per 2 users)
$@MK_AGGRO+=(.users/2);
// Mana Stone
if (.mp$ == "011-1")
enablenpc "Mana Stone";
// The Monster King will not move anymore because story
if ($GAME_STORYLINE == 0 ||
$GAME_STORYLINE >= 5) {
if (.mp$ != "boss")
unitwarp($@MK, "boss", 45, 45);
// Do not leave orphan timers
if ($GAME_STORYLINE >= 5)
stopnpctimer;
else
initnpctimer;
end;
}
// Check if MK is hurt, and if so, respawn it in boss map (summon cleanup)
if (getunitdata($@MK, UDT_HP) < getunitdata($@MK, UDT_MAXHP)) {
unitwarp($@MK, "boss", 45, 45);
sleep(50); // No exp for hitters
unitkill($@MK);
sleep(50); // No exp for hitters
$@MK=monster("boss", 45, 45, "The Monster King", MonsterKing, 1, "Monster King::OnBourneAgain");
// Monster King shall keep tending to his wounds in the keep for a cycle
initnpctimer;
end;
}
// Select a random map. Never shows up at Candor and cities, nor indoors. Not all maps either.
setarray .@m$, "boss", "boss", "001-1", "001-3", "001-4", "001-5", "001-6", "001-7", "001-10",
"003-1", "003-1-3", "004-1", "004-2", "007-1", "009-1", "010-1", "010-1-1", "010-2", "011-1",
"012-1", "014-1", "014-2", "014-3", "014-4", "014-5", "015-1", "015-2", "015-3", "015-5",
"018-1-1", "018-2", "018-3", "018-4", "018-4-1",
"019-1", "019-2", "019-4", "020-1", "021-1", "022-1", "023-1";
.mp$=any_of(.@m$);
// Try to warp randomly, up to 30 attempts
.@e=0; .@x=0; .@y=0;
.@mx=getmapinfo(MAPINFO_SIZE_X, .mp$)-20;
.@my=getmapinfo(MAPINFO_SIZE_Y, .mp$)-20;
do {
if (.@e >= 30) {
.mp$="boss";
.@x=45;
.@y=45;
break;
}
.@x = rand2(20, .@mx);
.@y = rand2(20, .@my);
.@e+=1;
} while (!checknpccell(.mp$, .@x, .@y, cell_chkpass));
if (!checknpccell(.mp$, .@x, .@y, cell_chkpass)) {
Exception("mk.bot runtime error: GM_ERR_128 highlight @Jesusalva", RB_DEBUGMES|RB_IRCBROADCAST); .mp$="boss"; .@x=45; .@y=45;
}
// Monster King will not warp around for sightseeing if he is threatened
if ($GAME_STORYLINE > 2 && $@MK_AGGRO < 150) {
.mp$="boss";.@x=45;.@y=45;
}
unitwarp($@MK, .mp$, .@x, .@y);
sleep(50); // For some reason or other, adding sleep(norid) and sleep2(rid).
.nearby=getusers(8);
// Handle Mana Stone
if (.mp$ == "011-1")
disablenpc "Mana Stone";
// Debug markers
if ($@GM_OVERRIDE)
debugmes "Monster King (bot): "+.mp$+" ("+.@x+", "+.@y+")";
// If too few players are online, we don't need an event AT ALL!
if (.users < rand2(2,4)) {
initnpctimer;
end;
}
// Siege events (req. 300 aggro, 3 users, and 70% chances to begin)
if ($@MK_AGGRO >= ($GAME_STORYLINE == 2 ? 300 : 900) && .users >= 3 && rand2(0,100) < 70 &&
is_between(1, 4, $GAME_STORYLINE) && $@MK_THROTTLE < gettimetick(2) &&
$@MK_TRIGGERED){
// Delta handles the compulsory wait time between waves.
// 7 hours normally, 24 hours if the army is in disarray.
.@delta=7;
$@SIEGE_ABORTED = false;
if ($GAME_STORYLINE >= 3)
.@delta=24;
// Tulimshar
if (compare(.mp$, "003-")) {
announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
$@MK_THROTTLE=gettimetick(2)+.@delta*60*60;
$@MK_SCENE=MK_SIEGE_TULIM;
donpcevent("Lieutenant Dausen::OnMKSiege");
}
// Halinarzo
else if (compare(.mp$, "009-")) {
announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
$@MK_THROTTLE=gettimetick(2)+.@delta*60*60;
$@MK_SCENE=MK_SIEGE_HALIN;
donpcevent("Lieutenant Jacob::OnMKSiege");
}
// Hurnscald
else if (compare(.mp$, "012-")) {
announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
$@MK_THROTTLE=gettimetick(2)+.@delta*60*60;
$@MK_SCENE=MK_SIEGE_HURNS;
donpcevent("#HurnscaldSiege::OnMKSiege");
}
// Nivalis
else if (compare(.mp$, "020-")) {
announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
$@MK_THROTTLE=gettimetick(2)+.@delta*60*60;
$@MK_SCENE=MK_SIEGE_NIVAL;
donpcevent("Lieutenant Joshua::OnMKSiege");
}
}
// If a player is nearby while the Monster King prepares, event may happen
// Minimum 80 Aggro
if (.nearby > 1 && $@MK_AGGRO >= 80 &&
($GAME_STORYLINE == 1 || ($GAME_STORYLINE >= 3 && $@MK_THROTTLE >= gettimetick(2)) )){
// We should decide event kind, but that's NYI
announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
getmapxy(.@m$, .@x, .@y, UNITTYPE_MOB, $@MK);
// Spawn stuff
areamonster(.@m$, .@x-20, .@y-20, .@x+20, .@y+20, "Monster", ManaGhost, min(60, $@MK_AGGRO/10)+.nearby, "Monster King::OnSlaveDie");
// Remove some aggro. TODO: Do not remove so much aggro if it was high
.@diff=($@MK_AGGRO*$GAME_STORYLINE)/5;
$@MK_AGGRO=max(.@diff, 0);
}
// Maybe, just maybe, game storyline must be updated here
if ($GAME_STORYLINE == 1 && $MK_TEMPVAR &&
$MK_TEMPVAR <= gettimeparam(GETTIME_DAYOFMONTH)) {
// Game Story Change: Idle MK -> Active MK
kamibroadcast("I can't handle it anymore! NO MORE!", "Monster King");
sleep(2500);
kamibroadcast("Come, my minions! Lay siege to towns! LEAVE NO OPPOSITION TO ME!", "Monster King");
sleep(2500);
kamibroadcast("Burn, destroy, do whatever you need, until your last breath, my lieutenants and colonels!", "Monster King");
sleep(2500);
kamibroadcast("##4 .:: Game Story Instructions on #world ::.");
channelmes("#world", "##1 **GAME STORY CHANGE** - The Monster King minions will now attack cities and lay waste to them.");
channelmes("#world", "##1 Players must defeat the lieutenants and colonels in order to prevent sieges from continuing.");
// Apply the changes
$GAME_STORYLINE=2;
$MK_TEMPVAR=0;
}
if ($GAME_STORYLINE == 2 &&
$MK_TEMPVAR >= MK_SIEGE_TOTALPOWER) {
kamibroadcast("##1##BThe Monster King army is in total disarray and disorder!", "Saulc");
sleep(2500);
kamibroadcast("##1##BIt's our chance to strike back!", "Saulc");
sleep(2500);
// Apply the changes
$GAME_STORYLINE=3;
$MK_TEMPVAR=0; // In past, we forced 1 month wait. Now we have KW mechs...
$MANA_BLVL-=10; // Set level to 20~30
$MANA_JLVL-=5; // Set job level to 15
}
// We're done, restart loop timer
$@MK_TRIGGERED=false;
initnpctimer;
end;
}
|