summaryrefslogtreecommitdiff
path: root/npc/functions/gmbot.txt
blob: d2cb3081ae6406b703543d1efd0f2ddc9a3b0e89 (plain) (blame)
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
// 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 in progress. 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
//      Stage TBD

000-0,0,0,0	script	Monster King	NPC_HIDDEN,{
OnSlaveDie:
    end;
OnBourneAgain:
    if (playerattached()) {
        channelmes("#world", strcharinfo(0)+" did an act worth of notice.");
        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.");
        getexp BaseLevel**3, 0;
        Mobpt = Mobpt + 165;
        $MOST_HEROIC$=strcharinfo(0);
    }
    // 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="200000";
    .cid="150002";
    // Constants

    // 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;
    }

    // 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 == 4) {
        if (.mp$ != "boss")
            unitwarp($@MK, "boss", 45, 45);
        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;
    do {
        if (.@e >= 30) {
            .mp$="boss";
            .@x=45;
            .@y=45;
            break;
        }
        .@x = rand(20, 300);
        .@y = rand(20, 300);
        .@e+=1;
    } while (!checknpccell(.mp$, .@x, .@y, cell_chkpass));
    if (!checknpccell(.mp$, .@x, .@y, cell_chkpass)) {
        Exception("gm.bot runtime error: GM_ERR_128 highlight @Jesusalva", RB_DEBUGMES|RB_IRCBROADCAST); .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 < rand(2,4)) {
        initnpctimer;
        end;
    }

    // Siege events (req. 300 aggro, 3 users, and 70% chances to begin)
    if ($@MK_AGGRO >= 300 && .users >= 3 && rand(0,100) < 70 &&
        $GAME_STORYLINE == 2 && $@MK_THROTTLE < gettimetick(2)){
        // Tulimshar
        if (.mp$ ~= "003-*") {
            announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
            $@MK_THROTTLE=gettimetick(2)+8*60*60;
            $@MK_SCENE=MK_SIEGE_TULIM;
            donpcevent("Lieutenant Dausen::OnMKSiege");
        }
        // Halinarzo
        else if (.mp$ ~= "009-*") {
            announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
            $@MK_THROTTLE=gettimetick(2)+8*60*60;
            $@MK_SCENE=MK_SIEGE_HALIN;
            donpcevent("Lieutenant Jacob::OnMKSiege");
        }
        // Hurnscald
        else if (.mp$ ~= "012-*") {
            announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
            $@MK_THROTTLE=gettimetick(2)+8*60*60;
            $@MK_SCENE=MK_SIEGE_HURNS;
            donpcevent("#HurnscaldSiege::OnMKSiege");
        }
        // Nivalis
        else if (.mp$ ~= "020-*") {
            announce ("Monster King: I smell humans! Humans must die!"), bc_map|bc_npc;
            $@MK_THROTTLE=gettimetick(2)+8*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 60 Aggro
    if (.nearby > 1 && $@MK_AGGRO >= 80 &&
        ($GAME_STORYLINE == 1 || $GAME_STORYLINE == 3)){
        // 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);
        // 50% more monsters at night time
        if (is_night())
            $@MK_AGGRO=$@MK_AGGRO*3/2;

        // Spawn stuff
        areamonster(.@m$, .@x-20, .@y-20, .@x+20, .@y+20, "Monster", ManaGhost, ($@MK_AGGRO/10)+.nearby, "Monster King::OnSlaveDie");
        $@MK_AGGRO=$@MK_AGGRO/5;
    }

    // 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 >= 500) {
        kamibroadcast("The Monster King army is in total disarray and disorder!", "Saulc | The Alliance");
        sleep(2500);
        kamibroadcast("It's our chance to strike back!", "Saulc | The Alliance");
        sleep(2500);

        // Apply the changes
        $GAME_STORYLINE=3;
        $MK_TEMPVAR=0; // In past, we forced 1 month wait. Now we have KW mechs...
    }

    // We're done, restart loop timer
    initnpctimer;
    end;
}