1 // koth.cpp : Defines the entry point for the DLL application.
2
3 #include "bzfsAPI.h"
4 #include <map>
5 #include <cmath>
6
7 class KOTHMapHandler : public bz_CustomMapObjectHandler
8 {
9 public:
10 virtual bool MapObject ( bz_ApiString object, bz_CustomMapObjectInfo *data );
11 };
12
13 KOTHMapHandler kothmaphandler;
14
15 class KOTHCommands : public bz_CustomSlashCommandHandler
16 {
17 public:
~KOTHCommands()18 virtual ~KOTHCommands() {};
19 virtual bool SlashCommand ( int playerID, bz_ApiString command, bz_ApiString message, bz_APIStringList *param );
20 };
21
22 KOTHCommands kothcommands;
23
24 class KOTHHandler : public bz_Plugin
25 {
26 public:
Name()27 virtual const char* Name ()
28 {
29 return "King Of The Hill";
30 }
31 virtual void Init ( const char* config );
32 virtual void Cleanup ();
33
34 virtual void Event ( bz_EventData *eventData );
35
36 };
37
BZ_PLUGIN(KOTHHandler)38 BZ_PLUGIN(KOTHHandler)
39
40 void KOTHHandler::Init(const char* /*commandLine*/)
41 {
42 MaxWaitTime = 0.5f;
43
44 bz_registerCustomMapObject("KOTH",&kothmaphandler);
45 Register(bz_ePlayerUpdateEvent);
46 Register(bz_ePlayerPausedEvent);
47 Register(bz_ePlayerPartEvent);
48 Register(bz_ePlayerJoinEvent);
49 Register(bz_ePlayerDieEvent);
50 bz_registerCustomSlashCommand("kothstatus",&kothcommands);
51 bz_registerCustomSlashCommand("kothon",&kothcommands);
52 bz_registerCustomSlashCommand("kothoff",&kothcommands);
53 bz_registerCustomSlashCommand("kothsoundon",&kothcommands);
54 bz_registerCustomSlashCommand("kothsoundoff",&kothcommands);
55 bz_registerCustomSlashCommand("kothtimemult",&kothcommands);
56 bz_registerCustomSlashCommand("kothtimemultmin",&kothcommands);
57 bz_registerCustomSlashCommand("kothtime",&kothcommands);
58 bz_registerCustomSlashCommand("kothautotimeon",&kothcommands);
59 bz_registerCustomSlashCommand("kothautotimeoff",&kothcommands);
60 bz_registerCustomSlashCommand("kingsay",&kothcommands);
61 }
62
Cleanup(void)63 void KOTHHandler::Cleanup(void)
64 {
65
66 Flush();
67 bz_removeCustomMapObject("KOTH");
68 bz_removeCustomSlashCommand("kothstatus");
69 bz_removeCustomSlashCommand("kothon");
70 bz_removeCustomSlashCommand("kothoff");
71 bz_removeCustomSlashCommand("kothsoundon");
72 bz_removeCustomSlashCommand("kothsoundoff");
73 bz_removeCustomSlashCommand("kothtimemult");
74 bz_removeCustomSlashCommand("kothtimemultmin");
75 bz_removeCustomSlashCommand("kothtime");
76 bz_removeCustomSlashCommand("kothautotimeon");
77 bz_removeCustomSlashCommand("kothautotimeoff");
78 bz_removeCustomSlashCommand("kingsay");
79 }
80
81 class KOTH
82 {
83 public:
KOTH()84 KOTH()
85 {
86 id = -1;
87 startTime = 0;
88 team = eNoTeam;
89 callsign = "";
90 teamPlay = false;
91 TTH = 60;
92 adjustedTime = 60;
93 timeMult = 0.03;
94 timeMultMin = 0.50;
95 enabled = true;
96 toldHillOpen = false;
97 onePlayerWarn = false;
98 autoTimeOn = false;
99 TTHminutes = 0;
100 TTHseconds = 30;
101 playerJustWon = -1;
102 soundEnabled = true;
103 }
104 bz_eTeamType team;
105 std::string callsign;
106 double TTH;
107 double adjustedTime;
108 double timeMult;
109 double timeMultMin;
110 double startTime;
111 bool teamPlay;
112 bool enabled;
113 bool toldHillOpen;
114 bool onePlayerWarn;
115 bool autoTimeOn;
116 bool soundEnabled;
117 int TTHminutes;
118 int TTHseconds;
119 int playerJustWon;
120 int id;
121 };
122
123 KOTH koth;
124
125 class KOTHZone : public bz_CustomZoneObject
126 {
127 public:
KOTHZone()128 KOTHZone() : bz_CustomZoneObject() {}
129 };
130
131 KOTHZone kothzone;
132
MapObject(bz_ApiString object,bz_CustomMapObjectInfo * data)133 bool KOTHMapHandler::MapObject ( bz_ApiString object, bz_CustomMapObjectInfo *data )
134 {
135 if (object != "KOTH" || !data)
136 return false;
137
138 kothzone.handleDefaultOptions(data);
139
140 // parse all the chunks
141 for ( unsigned int i = 0; i < data->data.size(); i++ )
142 {
143 std::string line = data->data.get(i).c_str();
144
145 bz_APIStringList *nubs = bz_newStringList();
146 nubs->tokenize(line.c_str()," ",0,true);
147
148 if ( nubs->size() > 0)
149 {
150 std::string key = bz_toupper(nubs->get(0).c_str());
151
152 if ( key == "TEAMPLAY")
153 koth.teamPlay = true;
154 else if ( key == "NOSOUND")
155 koth.soundEnabled = false;
156 else if ( key == "AUTOTIME" && nubs->size() == 1 )
157 koth.autoTimeOn = true;
158 else if ( key == "AUTOTIME" && nubs->size() > 2 )
159 {
160 double temp1 = (double)atof(nubs->get(1).c_str());
161 double temp2 = (double)atof(nubs->get(2).c_str());
162 if (temp1 >= 1 && temp1 <= 99)
163 koth.timeMult = temp1 / 100;
164 if (temp2 >= 1 && temp2 <= 99)
165 koth.timeMultMin = temp2 / 100;
166 koth.autoTimeOn = true;
167 }
168 else if ( key == "HOLDTIME" && nubs->size() > 1 )
169 {
170 double temp = (double)atof(nubs->get(1).c_str());
171 if (temp >= 1 && temp <= 7200)
172 koth.TTH = temp;
173 }
174 }
175
176 bz_deleteStringList(nubs);
177 }
178 return true;
179 }
180
truncate(std::string cllsn)181 std::string truncate(std::string cllsn)
182 {
183 std::string fixed = "";
184
185 for (int i = 0; i < 16; i++)
186 fixed.push_back(cllsn[i]);
187
188 fixed.append("~");
189
190 return fixed;
191 }
192
getTeamColor(bz_eTeamType testteam)193 const char* getTeamColor(bz_eTeamType testteam)
194 {
195 if (testteam == eRedTeam)
196 return "RED";
197 if (testteam == eGreenTeam)
198 return "GREEN";
199 if (testteam == eBlueTeam)
200 return "BLUE";
201 if (testteam == ePurpleTeam)
202 return "PURPLE";
203 if (testteam == eRogueTeam)
204 return "ROGUE";
205
206 return " ";
207 }
208
onePlayer()209 bool onePlayer()
210 {
211 int numPlayers = bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(
212 ePurpleTeam) + bz_getTeamCount(eRogueTeam);
213
214 if (numPlayers <= 1)
215 {
216 if (!koth.onePlayerWarn)
217 bz_sendTextMessage (BZ_SERVER, BZ_ALLUSERS, "King of the Hill disabled: less than 2 players.");
218
219 koth.onePlayerWarn = true;
220 return true;
221 }
222 else
223 {
224 if (koth.onePlayerWarn)
225 bz_sendTextMessage (BZ_SERVER, BZ_ALLUSERS, "King of the Hill enabled: more than 1 player.");
226
227 koth.onePlayerWarn = false;
228 return false;
229 }
230 }
231
autoTime()232 void autoTime()
233 {
234 int numPlayers = bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(
235 ePurpleTeam) + bz_getTeamCount(eRogueTeam);
236
237 if (!koth.autoTimeOn || numPlayers < 3)
238 {
239 koth.adjustedTime = koth.TTH;
240 return;
241 }
242
243 double timeDown = ( 1 - ((double)numPlayers - 2) * koth.timeMult);
244
245 if (timeDown < koth.timeMultMin)
246 timeDown = koth.timeMultMin;
247
248 koth.adjustedTime = (int)(koth.TTH * timeDown);
249
250 return;
251 }
252
ConvertToNum(std::string inmessage,double minNum,double maxNum)253 double ConvertToNum(std::string inmessage, double minNum, double maxNum)
254 {
255
256 int messagelength = (int)inmessage.length();
257
258 if (messagelength > 0 && messagelength < 5)
259 {
260 double messagevalue = 0;
261 double tens = 1;
262
263 for ( int i = (messagelength - 1); i >= 0; i-- )
264 {
265
266 if (inmessage[i] < '0' || inmessage[i] > '9') // got something other than a number
267 return 0;
268
269 tens *= 10;
270 messagevalue += (((double)inmessage[i] - '0') / 10) * tens;
271 }
272
273 if (messagevalue >= minNum && messagevalue <= maxNum)
274 return messagevalue;
275 }
276
277 return 0;
278 }
279
killTeams(bz_eTeamType safeteam,std::string kothcallsign)280 void killTeams(bz_eTeamType safeteam, std::string kothcallsign)
281 {
282 bz_APIIntList *playerList = bz_newIntList();
283 bz_getPlayerIndexList ( playerList );
284
285 for ( unsigned int i = 0; i < playerList->size(); i++ )
286 {
287
288 bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i));
289
290 if (player)
291 {
292
293 if (player->team != safeteam)
294 {
295 bz_killPlayer(player->playerID, true, BZ_SERVER);
296 if (koth.soundEnabled)
297 bz_sendPlayCustomLocalSound(player->playerID,"flag_lost");
298 }
299 else if (koth.soundEnabled)
300 bz_sendPlayCustomLocalSound(player->playerID,"flag_won");
301 }
302
303 bz_freePlayerRecord(player);
304 }
305 bz_deleteIntList(playerList);
306
307 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s (%s) IS KING OF THE HILL!", getTeamColor(safeteam),
308 kothcallsign.c_str());
309
310 return;
311 }
312
killPlayers(int safeid,std::string kothcallsign)313 void killPlayers(int safeid, std::string kothcallsign)
314 {
315 bz_APIIntList *playerList = bz_newIntList();
316 bz_getPlayerIndexList ( playerList );
317
318 for ( unsigned int i = 0; i < playerList->size(); i++ )
319 {
320
321 bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i));
322
323 if (player)
324 {
325
326 if (player->playerID != safeid)
327 {
328 bz_killPlayer(player->playerID, true, koth.id);
329 if (koth.soundEnabled)
330 bz_sendPlayCustomLocalSound(player->playerID,"flag_lost");
331 }
332 else if (koth.soundEnabled)
333 bz_sendPlayCustomLocalSound(player->playerID,"flag_won");
334 }
335
336 bz_freePlayerRecord(player);
337 }
338
339 bz_deleteIntList(playerList);
340
341 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s IS KING OF THE HILL!", kothcallsign.c_str());
342
343 return;
344 }
345
sendWarnings(const char * teamcolor,std::string playercallsign,double kothstartedtime)346 void sendWarnings(const char* teamcolor, std::string playercallsign, double kothstartedtime)
347 {
348 double TimeElapsed = bz_getCurrentTime() - kothstartedtime;
349 double TimeRemaining = koth.adjustedTime - TimeElapsed;
350 int toTens = int((TimeRemaining + 5) / 10) * 10;
351
352 if ((TimeRemaining/60) < koth.TTHminutes && koth.adjustedTime > 59)
353 {
354 if (!koth.teamPlay || koth.team == eRogueTeam)
355 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s will be King in %i secs!", playercallsign.c_str(), toTens);
356 else
357 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s (%s) will be King in %i secs!", teamcolor, playercallsign.c_str(),
358 toTens);
359
360 koth.TTHminutes--;
361 }
362
363 if (koth.adjustedTime < koth.TTHseconds)
364 {
365 koth.TTHseconds = koth.TTHseconds - 10;
366 return;
367 }
368
369 if (TimeRemaining < koth.TTHseconds)
370 {
371 if (!koth.teamPlay || koth.team == eRogueTeam)
372 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s will be King in %i secs!", playercallsign.c_str(), koth.TTHseconds);
373 else
374 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s (%s) will be King in %i secs!", teamcolor, playercallsign.c_str(),
375 koth.TTHseconds);
376
377 koth.TTHseconds = koth.TTHseconds - 10;
378 }
379 return;
380 }
381
initiatekoth(bz_eTeamType plyrteam,bz_ApiString plyrcallsign,int plyrID)382 void initiatekoth(bz_eTeamType plyrteam, bz_ApiString plyrcallsign, int plyrID)
383 {
384 koth.team = plyrteam;
385 koth.callsign = plyrcallsign.c_str();
386
387 if (koth.callsign.size() > 16)
388 {
389 std::string tofix = truncate(koth.callsign);
390 koth.callsign = tofix;
391 }
392
393 koth.id = plyrID;
394 koth.startTime = bz_getCurrentTime();
395 koth.TTHminutes = (int)(koth.adjustedTime/60 + 0.5);
396 koth.TTHseconds = 30;
397 koth.toldHillOpen = false;
398 bool multipleof30 = false;
399
400 if ((int)((koth.adjustedTime / 30) + 0.5) != (double)(koth.adjustedTime / 30))
401 multipleof30 = false;
402 else
403 multipleof30 = true;
404
405 if (!multipleof30)
406 {
407 if ((!koth.teamPlay || koth.team == eRogueTeam))
408 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s has Hill; will be King in %i secs!", koth.callsign.c_str(),
409 (int)koth.adjustedTime);
410 else
411 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s (%s) has Hill; will be King in %i secs!", getTeamColor(koth.team),
412 koth.callsign.c_str(), (int)koth.adjustedTime);
413 }
414
415 if (koth.soundEnabled)
416 {
417 bz_APIIntList *playerList = bz_newIntList();
418 bz_getPlayerIndexList ( playerList );
419
420 for ( unsigned int i = 0; i < playerList->size(); i++ )
421 {
422 bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i));
423
424 if (player)
425 {
426 if (player->team != koth.team)
427 bz_sendPlayCustomLocalSound(player->playerID,"flag_alert");
428 else
429 bz_sendPlayCustomLocalSound(player->playerID,"teamgrab");
430 }
431
432 bz_freePlayerRecord(player);
433 }
434 bz_deleteIntList(playerList);
435 }
436
437 return;
438 }
439
teamClear(bz_eTeamType teamToCheck)440 bool teamClear(bz_eTeamType teamToCheck)
441 {
442 if (teamToCheck == eRogueTeam || teamToCheck == eNoTeam || !koth.teamPlay)
443 return true;
444
445 bz_APIIntList *playerList = bz_newIntList();
446 bz_getPlayerIndexList ( playerList );
447
448 bool isOut = true;
449
450 for ( unsigned int i = 0; i < playerList->size(); i++ )
451 {
452
453 bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i));
454
455 if (player)
456 {
457 if (player->team == teamToCheck && kothzone.pointInZone(player->lastKnownState.pos) && player->spawned)
458 isOut = false;
459 }
460
461 bz_freePlayerRecord(player);
462 }
463
464 bz_deleteIntList(playerList);
465
466 return isOut;
467 }
468
KOTHPlayerPaused(bz_EventData * eventData)469 void KOTHPlayerPaused ( bz_EventData *eventData )
470 {
471 if (eventData->eventType != bz_ePlayerPausedEvent || !koth.enabled)
472 return;
473
474 bz_PlayerPausedEventData_V1 *PauseData = (bz_PlayerPausedEventData_V1*)eventData;
475 bz_BasePlayerRecord *player = bz_getPlayerByIndex(PauseData->playerID);
476
477 if (player)
478 {
479 if (kothzone.pointInZone(player->lastKnownState.pos))
480 {
481 bz_killPlayer (PauseData->playerID, true, BZ_SERVER);
482 bz_sendTextMessage (BZ_SERVER, PauseData->playerID, "Cannot pause while on the Hill.");
483 }
484 }
485 bz_freePlayerRecord(player);
486
487 return;
488 }
489
KOTHPlayerJoined(bz_EventData * eventData)490 void KOTHPlayerJoined ( bz_EventData *eventData )
491 {
492 if (eventData->eventType != bz_ePlayerJoinEvent || !koth.enabled)
493 return;
494
495 autoTime();
496
497 return;
498 }
499
KOTHPlayerLeft(bz_EventData * eventData)500 void KOTHPlayerLeft ( bz_EventData *eventData )
501 {
502 if (eventData->eventType != bz_ePlayerPartEvent || !koth.enabled)
503 return;
504
505 autoTime();
506
507 bz_PlayerJoinPartEventData_V1 *partData = (bz_PlayerJoinPartEventData_V1*)eventData;
508
509 if (partData->playerID == koth.id)
510 {
511 koth.id = -1;
512 koth.team = eNoTeam;
513 }
514
515 return;
516 }
517
KOTHPlayerDied(bz_EventData * eventData)518 void KOTHPlayerDied( bz_EventData *eventData )
519 {
520 if (eventData->eventType != bz_ePlayerDieEvent || !koth.enabled)
521 return;
522
523 bz_PlayerDieEventData_V1 *dieData = (bz_PlayerDieEventData_V1*)eventData;
524
525 if (dieData->playerID == koth.id)
526 {
527 koth.id = -1;
528 koth.team = eNoTeam;
529 }
530
531 return;
532 }
533
KOTHEventHandler(bz_EventData * eventData)534 inline void KOTHEventHandler( bz_EventData *eventData )
535 {
536 if (!koth.enabled) // King of the Hill disabled - we can leave
537 return;
538
539 if (onePlayer()) // Not enough players - we can leave
540 return;
541
542 float pos[3] = {0};
543
544 int playerID = -1;
545
546 switch (eventData->eventType)
547 {
548 case bz_ePlayerUpdateEvent:
549 pos[0] = ((bz_PlayerUpdateEventData_V1*)eventData)->state.pos[0];
550 pos[1] = ((bz_PlayerUpdateEventData_V1*)eventData)->state.pos[1];
551 pos[2] = ((bz_PlayerUpdateEventData_V1*)eventData)->state.pos[2];
552 playerID = ((bz_PlayerUpdateEventData_V1*)eventData)->playerID;
553 break;
554
555 case bz_eShotFiredEvent:
556 pos[0] = ((bz_ShotFiredEventData_V1*)eventData)->pos[0];
557 pos[1] = ((bz_ShotFiredEventData_V1*)eventData)->pos[1];
558 pos[2] = ((bz_ShotFiredEventData_V1*)eventData)->pos[2];
559 playerID = ((bz_ShotFiredEventData_V1*)eventData)->playerID;
560 break;
561
562 default:
563 return;
564 }
565
566 if (!koth.toldHillOpen && koth.id == -1) // Hill is open - inform players
567 {
568 bz_sendTextMessage (BZ_SERVER, BZ_ALLUSERS, "Hill is not controlled - take it!");
569 koth.toldHillOpen = true;
570 }
571
572 if (kothzone.pointInZone(pos)) // player is on Hill
573 {
574 bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
575
576 if (player)
577 {
578 if (player->playerID != koth.playerJustWon && player->spawned)
579 {
580 if ((koth.id == -1 && player->team != koth.team) || (koth.id == -1 && teamClear(koth.team)))
581 initiatekoth(player->team, player->callsign, player->playerID);
582
583 double timeStanding = bz_getCurrentTime() - koth.startTime;
584
585 if (timeStanding >= koth.adjustedTime && koth.id != -1) // time's up - kill 'em
586 {
587 if (koth.teamPlay && koth.team != eRogueTeam)
588 killTeams(koth.team, koth.callsign);
589 else
590 killPlayers(koth.id, koth.callsign);
591
592 if (!koth.teamPlay || koth.team == eRogueTeam)
593 bz_sendTextMessage (BZ_SERVER, koth.id, "You are King of the Hill! You must leave hill to retake it.");
594 else
595 bz_sendTextMessage (BZ_SERVER, koth.team, "Your team is King of the Hill! Entire team must leave hill to retake it.");
596
597 koth.playerJustWon = koth.id;
598
599 koth.id = -1;
600
601 return;
602 }
603 if (koth.id != -1)
604 sendWarnings(getTeamColor(koth.team), koth.callsign, koth.startTime);
605 }
606 }
607
608 bz_freePlayerRecord(player);
609 }
610 else // player is off Hill
611 {
612 if (playerID == koth.playerJustWon)
613 koth.playerJustWon = -1;
614
615 if (playerID == koth.id)
616 {
617 koth.id = -1;
618 koth.team = eNoTeam;
619 }
620 }
621 }
622
Event(bz_EventData * eventData)623 void KOTHHandler::Event( bz_EventData *eventData )
624 {
625 if (eventData->eventType == bz_ePlayerUpdateEvent)
626 KOTHEventHandler(eventData);
627 else if (eventData->eventType == bz_eShotFiredEvent)
628 KOTHEventHandler(eventData);
629 else if (eventData->eventType == bz_ePlayerDieEvent)
630 KOTHPlayerDied(eventData);
631 else if (eventData->eventType == bz_ePlayerJoinEvent)
632 KOTHPlayerJoined(eventData);
633 else if (eventData->eventType == bz_ePlayerPartEvent)
634 KOTHPlayerLeft(eventData);
635 else if (eventData->eventType == bz_ePlayerPausedEvent)
636 KOTHPlayerPaused(eventData);
637
638 }
639
640
SlashCommand(int playerID,bz_ApiString _command,bz_ApiString _message,bz_APIStringList *)641 bool KOTHCommands::SlashCommand ( int playerID, bz_ApiString _command, bz_ApiString _message,
642 bz_APIStringList * /*_param*/ )
643 {
644 std::string command = _command.c_str();
645 std::string message = _message.c_str();
646 const char* kingmessage = _message.c_str();
647
648 if ( command == "kingsay" )
649 {
650 if (koth.id != -1)
651 bz_sendTextMessage (playerID, koth.id, kingmessage);
652 else
653 bz_sendTextMessage(BZ_SERVER,playerID,"There is no one attempting to be king right now.");
654
655 return true;
656 }
657
658 bz_BasePlayerRecord *fromPlayer = bz_getPlayerByIndex(playerID);
659
660 if (fromPlayer)
661 {
662 if ( !fromPlayer->admin )
663 {
664 bz_sendTextMessage(BZ_SERVER,playerID,"You must be admin to use the koth commands.");
665 bz_freePlayerRecord(fromPlayer);
666 return true;
667 }
668
669 bz_freePlayerRecord(fromPlayer);
670 }
671
672 if ( command == "kothon")
673 {
674 koth.enabled = true;
675 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill is enabled.");
676 return true;
677 }
678
679 if ( command == "kothoff")
680 {
681 koth.enabled = false;
682 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill is disabled.");
683 return true;
684 }
685
686 if ( command == "kothsoundon")
687 {
688 koth.soundEnabled = true;
689 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill sounds are enabled.");
690 return true;
691 }
692
693 if ( command == "kothsoundoff")
694 {
695 koth.soundEnabled = false;
696 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill sounds are disabled.");
697 return true;
698 }
699
700 if ( command == "kothtimemult")
701 {
702 double inputvalue = ConvertToNum(message, 1, 99);
703
704 if (inputvalue > 0)
705 {
706 koth.timeMult = (inputvalue/100);
707 bz_sendTextMessagef (BZ_SERVER, playerID, "Auto time multiplier set to %i percent.", (int)(koth.timeMult*100 + 0.5));
708 }
709 else
710 bz_sendTextMessagef (BZ_SERVER, playerID, "Auto time multiplier must be between 1 and 99 percent.",
711 (int)(koth.timeMult*100 + 0.5));
712
713 autoTime();
714
715 return true;
716 }
717
718 if ( command == "kothtimemultmin")
719 {
720 double inputvalue = ConvertToNum(message, 1, 99);
721
722 if (inputvalue > 0)
723 {
724 koth.timeMultMin = (inputvalue/100);
725 bz_sendTextMessagef (BZ_SERVER, playerID, "Auto time multiplier minimum set to %i percent.",
726 (int)(koth.timeMultMin*100 + 0.5));
727 }
728 else
729 bz_sendTextMessagef (BZ_SERVER, playerID, "Auto time multiplier minimum must be between 1 and 99 percent.");
730
731 autoTime();
732
733 return true;
734 }
735
736 if ( command == "kothstatus")
737 {
738 if (koth.enabled)
739 bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill is currently enabled.");
740
741 if (!koth.enabled)
742 bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill is currently disabled.");
743
744 if (koth.soundEnabled)
745 bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill sounds are currently enabled.");
746
747 if (!koth.soundEnabled)
748 bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill sounds are currently disabled.");
749
750 if (koth.autoTimeOn)
751 bz_sendTextMessagef (BZ_SERVER, playerID, "Automatic time adjustment is currently enabled.");
752
753 if (!koth.autoTimeOn)
754 bz_sendTextMessagef (BZ_SERVER, playerID, "Automatic time adjustment is currently disabled.");
755
756 bz_sendTextMessagef (BZ_SERVER, playerID, "Time multiplier = %i percent.", (int)(koth.timeMult*100 + 0.5));
757
758 bz_sendTextMessagef (BZ_SERVER, playerID, "Time multiplier minimum = %i percent.", (int)(koth.timeMultMin*100 + 0.5));
759
760 int AdjTime = (int)(koth.adjustedTime + 0.5);
761 bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill hold time is currently set to: %i seconds", AdjTime);
762 return true;
763 }
764
765 // explicit time command handler:
766
767 if ( command == "kothtime" )
768 {
769 double inputvalue = ConvertToNum(message, 1, 7200);
770
771 if (inputvalue > 0 )
772 {
773 koth.TTH = inputvalue;
774 autoTime();
775 int AdjTime = (int)(inputvalue + 0.5);
776 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill hold time has been set to %i seconds.", AdjTime);
777 }
778 else
779 bz_sendTextMessagef (BZ_SERVER, playerID, "King of the Hill hold time invalid: must be between 1 and 7200 seconds.");
780
781 autoTime();
782
783 return true;
784 }
785
786 if ( command == "kothautotimeon")
787 {
788 koth.autoTimeOn = true;
789 autoTime();
790 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill automatic time adjustment on.");
791 return true;
792 }
793
794 if ( command == "kothautotimeoff")
795 {
796 koth.autoTimeOn = false;
797 koth.adjustedTime = koth.TTH;
798 autoTime();
799 bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "King of the Hill automatic time adjustment off.");
800 return true;
801 }
802
803 return false;
804 }
805 // Local Variables: ***
806 // mode: C++ ***
807 // tab-width: 4 ***
808 // c-basic-offset: 4 ***
809 // indent-tabs-mode: nil ***
810 // End: ***
811 // ex: shiftwidth=4 tabstop=4
812