Overview

Namespaces

  • Budabot
    • Core
      • Modules
    • User
      • Modules
  • None
  • Tyrence
    • Modules

Classes

  • AccessLevel
  • Budabot\Core\AccessManager
  • Budabot\Core\AdminManager
  • Budabot\Core\AOChat
  • Budabot\Core\AOChatPacket
  • Budabot\Core\AOChatQueue
  • Budabot\Core\AOExtMsg
  • Budabot\Core\AsyncHttp
  • Budabot\Core\AutoInject
  • Budabot\Core\BotRunner
  • Budabot\Core\Budabot
  • Budabot\Core\BuddylistManager
  • Budabot\Core\CacheManager
  • Budabot\Core\CacheResult
  • Budabot\Core\ClassLoader
  • Budabot\Core\ColorSettingHandler
  • Budabot\Core\CommandAlias
  • Budabot\Core\CommandManager
  • Budabot\Core\ConfigFile
  • Budabot\Core\DB
  • Budabot\Core\DBRow
  • Budabot\Core\EventLoop
  • Budabot\Core\EventManager
  • Budabot\Core\GuildChannelCommandReply
  • Budabot\Core\GuildManager
  • Budabot\Core\HelpManager
  • Budabot\Core\Http
  • Budabot\Core\HttpRequest
  • Budabot\Core\LegacyLogger
  • Budabot\Core\LimitsController
  • Budabot\Core\LoggerWrapper
  • Budabot\Core\MMDBParser
  • Budabot\Core\Modules\AdminController
  • Budabot\Core\Modules\AliasController
  • Budabot\Core\Modules\AltInfo
  • Budabot\Core\Modules\AltsController
  • Budabot\Core\Modules\BanController
  • Budabot\Core\Modules\BuddylistController
  • Budabot\Core\Modules\ColorsController
  • Budabot\Core\Modules\CommandlistController
  • Budabot\Core\Modules\CommandSearchController
  • Budabot\Core\Modules\ConfigController
  • Budabot\Core\Modules\EventlistController
  • Budabot\Core\Modules\HelpController
  • Budabot\Core\Modules\LogsController
  • Budabot\Core\Modules\PlayerLookupController
  • Budabot\Core\Modules\ProfileCommandReply
  • Budabot\Core\Modules\ProfileController
  • Budabot\Core\Modules\SettingsController
  • Budabot\Core\Modules\SQLController
  • Budabot\Core\Modules\SystemController
  • Budabot\Core\Modules\UsageController
  • Budabot\Core\Modules\WhitelistController
  • Budabot\Core\NumberSettingHandler
  • Budabot\Core\OptionsSettingHandler
  • Budabot\Core\PlayerHistory
  • Budabot\Core\PlayerHistoryManager
  • Budabot\Core\PlayerManager
  • Budabot\Core\Preferences
  • Budabot\Core\PrivateChannelCommandReply
  • Budabot\Core\PrivateMessageCommandReply
  • Budabot\Core\Registry
  • Budabot\Core\SettingHandler
  • Budabot\Core\SettingManager
  • Budabot\Core\SettingObject
  • Budabot\Core\SocketManager
  • Budabot\Core\SocketNotifier
  • Budabot\Core\SubcommandManager
  • Budabot\Core\Text
  • Budabot\Core\TextSettingHandler
  • Budabot\Core\Timer
  • Budabot\Core\TimerEvent
  • Budabot\Core\TimeSettingHandler
  • Budabot\Core\Util
  • Budabot\Core\xml
  • Budabot\User\Modules\AlienArmorController
  • Budabot\User\Modules\AlienBioController
  • Budabot\User\Modules\AlienMiscController
  • Budabot\User\Modules\AOSpeakController
  • Budabot\User\Modules\AOUController
  • Budabot\User\Modules\AXPController
  • Budabot\User\Modules\BankController
  • Budabot\User\Modules\BosslootController
  • Budabot\User\Modules\BroadcastController
  • Budabot\User\Modules\BuffPerksController
  • Budabot\User\Modules\CacheController
  • Budabot\User\Modules\ChatAssistController
  • Budabot\User\Modules\ChatCheckController
  • Budabot\User\Modules\ChatLeaderController
  • Budabot\User\Modules\ChatRallyController
  • Budabot\User\Modules\ChatSayController
  • Budabot\User\Modules\ChatTopicController
  • Budabot\User\Modules\CityWaveController
  • Budabot\User\Modules\CloakController
  • Budabot\User\Modules\ClusterController
  • Budabot\User\Modules\CountdownController
  • Budabot\User\Modules\DevController
  • Budabot\User\Modules\DingController
  • Budabot\User\Modules\EventsController
  • Budabot\User\Modules\FightController
  • Budabot\User\Modules\FindOrgController
  • Budabot\User\Modules\FindPlayerController
  • Budabot\User\Modules\FunController
  • Budabot\User\Modules\GitController
  • Budabot\User\Modules\GuideController
  • Budabot\User\Modules\GuildController
  • Budabot\User\Modules\HelpbotController
  • Budabot\User\Modules\HtmlDecodeController
  • Budabot\User\Modules\ImplantController
  • Budabot\User\Modules\ImplantDesignerController
  • Budabot\User\Modules\InactiveMemberController
  • Budabot\User\Modules\ItemsController
  • Budabot\User\Modules\KillOnSightController
  • Budabot\User\Modules\LevelController
  • Budabot\User\Modules\LinksController
  • Budabot\User\Modules\LootListsController
  • Budabot\User\Modules\MdbController
  • Budabot\User\Modules\MessageInfoCommandReply
  • Budabot\User\Modules\MockCommandReply
  • Budabot\User\Modules\NanoController
  • Budabot\User\Modules\NewsController
  • Budabot\User\Modules\NotesController
  • Budabot\User\Modules\OnlineController
  • Budabot\User\Modules\OrgHistoryController
  • Budabot\User\Modules\OrglistController
  • Budabot\User\Modules\OrgMembersController
  • Budabot\User\Modules\OSController
  • Budabot\User\Modules\PlayerHistoryController
  • Budabot\User\Modules\PlayfieldController
  • Budabot\User\Modules\PocketbossController
  • Budabot\User\Modules\PremadeImplantController
  • Budabot\User\Modules\PrivateChannelController
  • Budabot\User\Modules\QuoteController
  • Budabot\User\Modules\RaffleController
  • Budabot\User\Modules\RaidController
  • Budabot\User\Modules\RandomController
  • Budabot\User\Modules\RecipeController
  • Budabot\User\Modules\RelayController
  • Budabot\User\Modules\ReputationController
  • Budabot\User\Modules\ResearchController
  • Budabot\User\Modules\RunAsController
  • Budabot\User\Modules\SendTellController
  • Budabot\User\Modules\ShoppingController
  • Budabot\User\Modules\SilenceController
  • Budabot\User\Modules\SkillsController
  • Budabot\User\Modules\SpiritsController
  • Budabot\User\Modules\StopwatchController
  • Budabot\User\Modules\Teamspeak3
  • Budabot\User\Modules\TeamspeakController
  • Budabot\User\Modules\TestController
  • Budabot\User\Modules\TimeController
  • Budabot\User\Modules\TimerController
  • Budabot\User\Modules\TimezoneController
  • Budabot\User\Modules\TowerController
  • Budabot\User\Modules\TrackerController
  • Budabot\User\Modules\TrickleController
  • Budabot\User\Modules\UnixtimeController
  • Budabot\User\Modules\VoteController
  • Budabot\User\Modules\WeatherController
  • Budabot\User\Modules\WhatBuffsController
  • Budabot\User\Modules\WhereisController
  • Budabot\User\Modules\WhoisController
  • Budabot\User\Modules\WhoisOrgController
  • Budabot\User\Modules\WhompahController
  • Command
  • DefaultStatus
  • DefineCommand
  • Description
  • Event
  • HandlesCommand
  • Help
  • Inject
  • Instance
  • Intoptions
  • Matches
  • Options
  • Setting
  • Setup
  • Type
  • Tyrence\Modules\DemoResponseCommandReply
  • Tyrence\Modules\SameChannelResponseController
  • Visibility

Interfaces

  • Budabot\Core\CommandReply

Exceptions

  • Budabot\Core\InvalidHttpRequest
  • Budabot\Core\SQLException
  • Budabot\Core\StopExecutionException

Functions

  • Budabot\Core\isWindows
  • Budabot\Core\Modules\read_input
  • Overview
  • Namespace
  • Class
  1: <?php
  2: 
  3: namespace Budabot\User\Modules;
  4: 
  5: use Budabot\Core\AutoInject;
  6: use Budabot\Core\DB;
  7: use \stdClass;
  8: use PDO;
  9: 
 10: /**
 11:  * Authors: 
 12:  *  - Tyrence (RK2)
 13:  *
 14:  * @Instance
 15:  *
 16:  * Commands this class contains:
 17:  *  @DefineCommand(
 18:  *      command     = 'implantdesigner',
 19:  *      accessLevel = 'all',
 20:  *      description = 'Implant Designer',
 21:  *      help        = 'implantdesigner.txt',
 22:  *      alias       = 'impdesign'
 23:  *  )
 24:  */
 25: class ImplantDesignerController extends AutoInject {
 26: 
 27:     /**
 28:      * Name of the module.
 29:      * Set automatically by module loader.
 30:      */
 31:     public $moduleName;
 32:     
 33:     private $slots = array('head', 'eye', 'ear', 'rarm', 'chest', 'larm', 'rwrist', 'waist', 'lwrist', 'rhand', 'legs', 'lhand', 'feet');
 34:     private $grades = array('shiny', 'bright', 'faded');
 35:     
 36:     private $design;
 37:     
 38:     /**
 39:      * @Setup
 40:      */
 41:     public function setup() {
 42:         $this->design = new stdClass;
 43:         
 44:         $this->db->loadSQLFile($this->moduleName, "implant_design");
 45:         
 46:         $this->db->loadSQLFile($this->moduleName, "Ability");
 47:         $this->db->loadSQLFile($this->moduleName, "Cluster");
 48:         $this->db->loadSQLFile($this->moduleName, "ClusterImplantMap");
 49:         $this->db->loadSQLFile($this->moduleName, "ClusterType");
 50:         $this->db->loadSQLFile($this->moduleName, "EffectTypeMatrix");
 51:         $this->db->loadSQLFile($this->moduleName, "EffectValue");
 52:         $this->db->loadSQLFile($this->moduleName, "ImplantMatrix");
 53:         $this->db->loadSQLFile($this->moduleName, "ImplantType");
 54:         $this->db->loadSQLFile($this->moduleName, "Profession");
 55:         $this->db->loadSQLFile($this->moduleName, "Symbiant");
 56:         $this->db->loadSQLFile($this->moduleName, "SymbiantAbilityMatrix");
 57:         $this->db->loadSQLFile($this->moduleName, "SymbiantClusterMatrix");
 58:         $this->db->loadSQLFile($this->moduleName, "SymbiantProfessionMatrix");
 59:     }
 60:     
 61:     /**
 62:      * @HandlesCommand("implantdesigner")
 63:      * @Matches("/^implantdesigner$/i")
 64:      */
 65:     public function implantdesignerCommand($message, $channel, $sender, $sendto, $args) {
 66:         $blob = $this->getImplantDesignerBuild($sender);
 67:         $msg = $this->text->makeBlob("Implant Designer", $blob);
 68:         $sendto->reply($msg);
 69:     }
 70:     
 71:     private function getImplantDesignerBuild($sender) {
 72:         $design = $this->getDesign($sender, '@');
 73:     
 74:         $blob = $this->text->makeChatcmd("Results", "/tell <myname> implantdesigner results");
 75:         $blob .= "<tab>";
 76:         $blob .= $this->text->makeChatcmd("Clear All", "/tell <myname> implantdesigner clear");
 77:         $blob .= "\n-----------------\n\n";
 78: 
 79:         forEach ($this->slots as $slot) {
 80:             $blob .= $this->text->makeChatcmd($slot, "/tell <myname> implantdesigner $slot");
 81:             if (!empty($design->$slot)) {
 82:                 $blob .= $this->getImplantSummary($design->$slot);
 83:             } else {
 84:                 $blob .= "\n";
 85:             }
 86:             $blob .= "\n";
 87:         }
 88: 
 89:         return $blob;
 90:     }
 91:     
 92:     private function getImplantSummary($slotObj) {
 93:         if ($slotObj->symb !== null) {
 94:             $msg = " " . $slotObj->symb->name . "\n";
 95:         } else {
 96:             $ql = empty($slotObj->ql) ? 300 : $slotObj->ql;
 97:             $implant = $this->getImplantInfo($ql, $slotObj->shiny, $slotObj->bright, $slotObj->faded);
 98:             $msg = " QL" . $ql;
 99:             if ($implant !== null) {
100:                 $msg .= " - Treatment: {$implant->Treatment} {$implant->AbilityName}: {$implant->Ability}";
101:             }
102:             $msg .= "\n";
103:             
104:             forEach ($this->grades as $grade) {
105:                 if (empty($slotObj->$grade)) {
106:                     $msg .= "<tab><highlight>-Empty-<end>\n";
107:                 } else {
108:                     $effectTypeIdName = ucfirst(strtolower($grade)) . 'EffectTypeID';
109:                     $effectId = $implant->$effectTypeIdName;
110:                     $msg .= "<tab><highlight>{$slotObj->$grade}<end> (" . $this->getClusterModAmount($ql, $grade, $effectId) . ")\n";
111:                 }
112:             }
113:         }
114:         return $msg;
115:     }
116:     
117:     private function getClusterModAmount($ql, $grade, $effectId) {
118:         $sql =
119:             "SELECT
120:                 ID,
121:                 Name,
122:                 MinValLow,
123:                 MaxValLow,
124:                 MinValHigh,
125:                 MaxValHigh
126:             FROM
127:                 EffectTypeMatrix
128:             WHERE
129:                 ID = ?";
130: 
131:         $row = $this->db->queryRow($sql, $effectId);
132:         
133:         if ($ql < 201) {
134:             $minVal = $row->MinValLow;
135:             $maxVal = $row->MaxValLow;
136:             $minQl = 1;
137:             $maxQl = 200;
138:         } else {
139:             $minVal = $row->MinValHigh;
140:             $maxVal = $row->MaxValHigh;
141:             $minQl = 201;
142:             $maxQl = 300;
143:         }
144:         
145:         $modAmount = $this->util->interpolate($minQl, $maxQl, $minVal, $maxVal, $ql);
146:         if ($grade == 'bright') {
147:             $modAmount = round($modAmount * 0.6, 0);
148:         } else if ($grade == 'faded') {
149:             $modAmount = round($modAmount * 0.4, 0);
150:         }
151: 
152:         return $modAmount;
153:     }
154:     
155:     /**
156:      * @HandlesCommand("implantdesigner")
157:      * @Matches("/^implantdesigner clear$/i")
158:      */
159:     public function implantdesignerClearCommand($message, $channel, $sender, $sendto, $args) {
160:         $this->saveDesign($sender, '@', new stdClass);
161:         $msg = "Implant Designer has been cleared.";
162:         $sendto->reply($msg);
163:         
164:         // send results
165:         $blob = $this->getImplantDesignerBuild($sender);
166:         $msg = $this->text->makeBlob("Implant Designer", $blob);
167:         $sendto->reply($msg);
168:     }
169: 
170:     /**
171:      * @HandlesCommand("implantdesigner")
172:      * @Matches("/^implantdesigner (head|eye|ear|rarm|chest|larm|rwrist|waist|lwrist|rhand|legs|lhand|feet)$/i")
173:      */
174:     public function implantdesignerSlotCommand($message, $channel, $sender, $sendto, $args) {
175:         $slot = strtolower($args[1]);
176: 
177:         $blob .= $this->text->makeChatcmd("See Build", "/tell <myname> implantdesigner");
178:         $blob .= "<tab>";
179:         $blob .= $this->text->makeChatcmd("Clear this slot", "/tell <myname> implantdesigner $slot clear");
180:         $blob .= "<tab>";
181:         $blob .= $this->text->makeChatcmd("Require Ability", "/tell <myname> implantdesigner $slot require");
182:         $blob .= "\n-------------------------\n";
183:         $blob .= "<header2>Implants<end>  ";
184:         forEach (array(25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300) as $ql) {
185:             $blob .= $this->text->makeChatcmd($ql, "/tell <myname> implantdesigner $slot $ql") . " ";
186:         }
187:         $blob .= "\n\n" . $this->getSymbiantsLinks($slot);
188:         $blob .= "\n-------------------------\n\n";
189:         
190:         $design = $this->getDesign($sender, '@');
191:         $slotObj = $design->$slot;
192:         
193:         if ($slotObj->symb !== null) {
194:             $symb = $slotObj->symb;
195:             $blob .= $symb->name ."\n\n";
196:             $blob .= "<header2>Requirements<end>\n";
197:             $blob .= "Treatment: {$symb->Treatment}\n";
198:             $blob .= "Level: {$symb->Level}\n";
199:             forEach ($symb->reqs as $req){
200:                 $blob .= "{$req->Name}: {$req->Amount}\n";
201:             }
202:             $blob .= "\n<header2>Modifications<end>\n";
203:             forEach ($symb->mods as $mod){
204:                 $blob .= "{$mod->Name}: {$mod->Amount}\n";
205:             }
206:             $blob .= "\n\n";
207:         } else {
208:             $ql = empty($design->$slot->ql) ? 300 : $design->$slot->ql;
209:             $blob .= "<header2>QL<end> $ql";
210:             $implant = $this->getImplantInfo($ql, $design->$slot->shiny, $design->$slot->bright, $design->$slot->faded);
211:             if ($implant !== null) {
212:                 $blob .= " - Treatment: {$implant->Treatment} {$implant->AbilityName}: {$implant->Ability}";
213:             }
214:             $blob .= "\n\n";
215:             
216:             $blob .= "<header2>Shiny<end>";
217:             $blob .= $this->showClusterChoices($design, $slot, 'shiny');
218:             
219:             $blob .= "<header2>Bright<end>";
220:             $blob .= $this->showClusterChoices($design, $slot, 'bright');
221:             
222:             $blob .= "<header2>Faded<end>";
223:             $blob .= $this->showClusterChoices($design, $slot, 'faded');
224:         }
225:         
226:         $msg = $this->text->makeBlob("Implant Designer ($slot)", $blob);
227: 
228:         $sendto->reply($msg);
229:     }
230:     
231:     private function getSymbiantsLinks($slot) {
232:         $artilleryLink = $this->text->makeChatcmd("Artillery", "/tell <myname> symb $slot artillery");
233:         $controlLink = $this->text->makeChatcmd("Control", "/tell <myname> symb $slot control");
234:         $exterminationLink = $this->text->makeChatcmd("Extermination", "/tell <myname> symb $slot extermination");
235:         $infantryLink = $this->text->makeChatcmd("Infantry", "/tell <myname> symb $slot infantry");
236:         $supportLink = $this->text->makeChatcmd("Support", "/tell <myname> symb $slot support");
237:         return "<header2>Symbiants<end>  $artilleryLink  $controlLink  $exterminationLink  $infantryLink  $supportLink";
238:     }
239:     
240:     private function showClusterChoices($design, $slot, $grade) {
241:         $msg = '';
242:         if (!empty($design->$slot->$grade)) {
243:             $msg .= " - {$design->$slot->$grade}";
244:         }
245:         $msg .= "\n";
246:         $msg .= $this->text->makeChatcmd("-Empty-", "/tell <myname> implantdesigner $slot $grade clear") . "\n";
247:         $data = $this->getClustersForSlot($slot, $grade);
248:         forEach ($data as $row) {
249:             $msg .= $this->text->makeChatcmd($row->skill, "/tell <myname> implantdesigner $slot $grade $row->skill") . "\n";
250:         }
251:         $msg .= "\n\n";
252:         return $msg;
253:     }
254:     
255:     /**
256:      * @HandlesCommand("implantdesigner")
257:      * @Matches("/^implantdesigner (head|eye|ear|rarm|chest|larm|rwrist|waist|lwrist|rhand|legs|lhand|feet) (shiny|bright|faded|symb) (.+)$/i")
258:      */
259:     public function implantdesignerSlotAddClusterCommand($message, $channel, $sender, $sendto, $args) {
260:         $slot = strtolower($args[1]);
261:         $type = strtolower($args[2]);
262:         $item = $args[3];
263:         
264:         $design = $this->getDesign($sender, '@');
265:         $slotObj = &$design->$slot;
266:         
267:         if ($type == 'symb') {
268:             $sql = 
269:                 "SELECT
270:                     s.ID,
271:                     s.Name,
272:                     s.TreatmentReq,
273:                     s.LevelReq
274:                 FROM
275:                     Symbiant s
276:                     JOIN ImplantType i
277:                         ON s.SlotID = i.ImplantTypeID
278:                 WHERE
279:                     i.ShortName = ?
280:                     AND s.Name = ?";
281:             
282:             $symbRow = $this->db->queryRow($sql, $slot, $item);
283:             
284:             if ($symbRow === null) {
285:                 $msg = "Could not find symbiant <highlight>$item<end>.";
286:             } else {
287:                 // convert slot to symb
288:                 unset($slotObj->shiny);
289:                 unset($slotObj->bright);
290:                 unset($slotObj->faded);
291:                 unset($slotObj->ql);
292:                 
293:                 $symb = new stdClass;
294:                 $symb->name = $symbRow->Name;
295:                 $symb->Treatment = $symbRow->TreatmentReq;
296:                 $symb->Level = $symbRow->LevelReq;
297:                 
298:                 // add requirements
299:                 $sql = "SELECT a.Name, s.Amount FROM SymbiantAbilityMatrix s JOIN Ability a ON s.AbilityID = a.AbilityID WHERE SymbiantID = ?";
300:                 $symb->reqs = $this->db->query($sql, $symbRow->ID);
301:                 
302:                 // add mods
303:                 $sql = "SELECT c.LongName AS Name, s.Amount FROM SymbiantClusterMatrix s JOIN Cluster c ON s.ClusterID = c.ClusterID WHERE SymbiantID = ?";
304:                 $symb->mods = $this->db->query($sql, $symbRow->ID);
305:                 
306:                 $slotObj->symb = $symb;
307:                 $msg = "<highlight>$slot(symb)<end> has been set to <highlight>$symb->name<end>.";
308:             }
309:         } else {
310:             if (strtolower($item) == 'clear') {
311:                 if ($slotObj->$type === null) {
312:                     $msg = "There is no cluster in <highlight>$slot($type)<end>.";
313:                 } else {
314:                     unset($slotObj->$type);
315:                     $msg = "<highlight>$slot($type)<end> has been cleared.";
316:                 }
317:             } else {
318:                 unset($slotObj->$type);
319:                 $slotObj->$type = $item;
320:                 $msg = "<highlight>$slot($type)<end> has been set to <highlight>$item<end>.";
321:             }
322:         }
323:         
324:         $this->saveDesign($sender, '@', $design);
325:         
326:         $sendto->reply($msg);
327:     
328:         // send results
329:         $blob = $this->getImplantDesignerBuild($sender);
330:         $msg = $this->text->makeBlob("Implant Designer", $blob);
331:         $sendto->reply($msg);
332:     }
333:     
334:     /**
335:      * @HandlesCommand("implantdesigner")
336:      * @Matches("/^implantdesigner (head|eye|ear|rarm|chest|larm|rwrist|waist|lwrist|rhand|legs|lhand|feet) (\d+)$/i")
337:      */
338:     public function implantdesignerSlotQLCommand($message, $channel, $sender, $sendto, $args) {
339:         $slot = strtolower($args[1]);
340:         $ql = $args[2];
341:         
342:         $design = $this->getDesign($sender, '@');
343:         $slotObj = $design->$slot;
344:         unset($slotObj->symb);
345:         $slotObj->ql = $ql;
346:         $this->saveDesign($sender, '@', $design);
347:         
348:         $msg = "<highlight>$slot<end> has been set to QL <highlight>$ql<end>.";
349: 
350:         $sendto->reply($msg);
351:         
352:         // send results
353:         $blob = $this->getImplantDesignerBuild($sender);
354:         $msg = $this->text->makeBlob("Implant Designer", $blob);
355:         $sendto->reply($msg);
356:     }
357:     
358:     /**
359:      * @HandlesCommand("implantdesigner")
360:      * @Matches("/^implantdesigner (head|eye|ear|rarm|chest|larm|rwrist|waist|lwrist|rhand|legs|lhand|feet) clear$/i")
361:      */
362:     public function implantdesignerSlotClearCommand($message, $channel, $sender, $sendto, $args) {
363:         $slot = strtolower($args[1]);
364:         
365:         $design = $this->getDesign($sender, '@');
366:         unset($design->$slot);
367:         $this->saveDesign($sender, '@', $design);
368:         
369:         $msg = "<highlight>$slot<end> has been cleared.";
370: 
371:         $sendto->reply($msg);
372:         
373:         // send results
374:         $blob = $this->getImplantDesignerBuild($sender);
375:         $msg = $this->text->makeBlob("Implant Designer", $blob);
376:         $sendto->reply($msg);
377:     }
378: 
379:     /**
380:      * @HandlesCommand("implantdesigner")
381:      * @Matches("/^implantdesigner (head|eye|ear|rarm|chest|larm|rwrist|waist|lwrist|rhand|legs|lhand|feet) require$/i")
382:      */
383:     public function implantdesignerSlotRequireCommand($message, $channel, $sender, $sendto, $args) {
384:         $slot = strtolower($args[1]);
385: 
386:         $design = $this->getDesign($sender, '@');
387:         $slotObj = $design->$slot;
388:         if (empty($slotObj)) {
389:             $msg = "You must have at least one cluster filled to require an ability.";
390:         } else if (!empty($slotObj->symb)) {
391:             $msg = "You cannot require an ability for a symbiant.";
392:         } else if (empty($slotObj->shiny) && empty($slotObj->bright) && empty($slotObj->faded)) {
393:             $msg = "You must have at least one cluster filled to require an ability.";
394:         } else if (!empty($slotObj->shiny) && !empty($slotObj->bright) && !empty($slotObj->faded)) {
395:             $msg = "You must have at least one empty cluster to require an ability.";
396:         } else {
397:             $blob .= $this->text->makeChatcmd("See Build", "/tell <myname> implantdesigner");
398:             $blob .= "<tab>";
399:             $blob .= $this->text->makeChatcmd("Clear this slot", "/tell <myname> implantdesigner $slot clear");
400:             $blob .= "\n-------------------------\n\n";
401:             $blob .= $this->text->makeChatcmd($slot, "/tell <myname> implantdesigner $slot");
402:             $blob .= $this->getImplantSummary($slotObj) . "\n";
403:             $blob .= "Which ability do you want to require for $slot?\n\n";
404:             $data = $this->db->query("SELECT Name FROM Ability");
405:             forEach ($data as $row) {
406:                 $blob .= $this->text->makeChatcmd($row->Name, "/tell <myname> implantdesigner $slot require $row->Name") . "\n";
407:             }
408:             $msg = $this->text->makeBlob("Implant Designer Require Ability ($slot)", $blob);
409:         }
410: 
411:         $sendto->reply($msg);
412:     }
413: 
414:     /**
415:      * @HandlesCommand("implantdesigner")
416:      * @Matches("/^implantdesigner (head|eye|ear|rarm|chest|larm|rwrist|waist|lwrist|rhand|legs|lhand|feet) require (agility|intelligence|psychic|sense|strength|stamina)$/i")
417:      */
418:     public function implantdesignerSlotRequireAbilityCommand($message, $channel, $sender, $sendto, $args) {
419:         $slot = strtolower($args[1]);
420:         $ability = ucfirst(strtolower($args[2]));
421: 
422:         $design = $this->getDesign($sender, '@');
423:         $slotObj = $design->$slot;
424:         if (empty($slotObj)) {
425:             $msg = "You must have at least one cluster filled to require an ability.";
426:         } else if (!empty($slotObj->symb)) {
427:             $msg = "You cannot require an ability for a symbiant.";
428:         } else if (empty($slotObj->shiny) && empty($slotObj->bright) && empty($slotObj->faded)) {
429:             $msg = "You must have at least one cluster filled to require an ability.";
430:         } else if (!empty($slotObj->shiny) && !empty($slotObj->bright) && !empty($slotObj->faded)) {
431:             $msg = "You must have at least one empty cluster to require an ability.";
432:         } else {
433:             $blob .= $this->text->makeChatcmd("See Build", "/tell <myname> implantdesigner");
434:             $blob .= "<tab>";
435:             $blob .= $this->text->makeChatcmd("Clear this slot", "/tell <myname> implantdesigner $slot clear");
436:             $blob .= "\n-------------------------\n\n";
437:             $blob .= $this->text->makeChatcmd($slot, "/tell <myname> implantdesigner $slot");
438:             $blob .= $this->getImplantSummary($slotObj) . "\n";
439:             $blob .= "Combinations for <highlight>$slot<end> that will require $ability:\n";
440:             $params = [$ability];
441:             $sql = 
442:                 "SELECT
443:                     i.AbilityQL1,
444:                     i.AbilityQL200,
445:                     i.AbilityQL201,
446:                     i.AbilityQL300,
447:                     i.TreatQL1,
448:                     i.TreatQL200,
449:                     i.TreatQL201,
450:                     i.TreatQL300,
451:                     c1.LongName as ShinyEffect,
452:                     c2.LongName as BrightEffect,
453:                     c3.LongName as FadedEffect
454:                 FROM
455:                     ImplantMatrix i
456:                     JOIN Cluster c1
457:                         ON i.ShiningID = c1.ClusterID
458:                     JOIN Cluster c2
459:                         ON i.BrightID = c2.ClusterID
460:                     JOIN Cluster c3
461:                         ON i.FadedID = c3.ClusterID
462:                     JOIN Ability a
463:                         ON i.AbilityID = a.AbilityID
464:                 WHERE
465:                     a.Name = ?";
466: 
467:             if (!empty($slotObj->shiny)) {
468:                 $sql .= " AND c1.LongName = ?";
469:                 $params []= $slotObj->shiny;
470:             }
471:             if (!empty($slotObj->bright)) {
472:                 $sql .= " AND c2.LongName = ?";
473:                 $params []= $slotObj->bright;
474:             }
475:             if (!empty($slotObj->faded)) {
476:                 $sql .= " AND c3.LongName = ?";
477:                 $params []= $slotObj->faded;
478:             }
479:             $sql .= " ORDER BY c1.LongName, c2.LongName, c3.LongName";
480: 
481:             $data = $this->db->query($sql, $params);
482:             $primary = null;
483:             forEach ($data as $row) {
484:                 $results = [];
485:                 if (empty($slotObj->shiny)) {
486:                     $results []= ['shiny', $row->ShinyEffect];
487:                 }
488:                 if (empty($slotObj->bright)) {
489:                     $results []= ['bright', $row->BrightEffect];
490:                 }
491:                 if (empty($slotObj->faded)) {
492:                     $results []= ['faded', $row->FadedEffect];
493:                 }
494:                 $results = array_map(function($item) use($slot) {
495:                     return (empty($item[1]) ? '-Empty-' : $this->text->makeChatcmd($item[1], "/tell <myname> implantdesigner $slot {$item[0]} {$item[1]}"));
496:                 }, $results);
497:                 if ($results[0] != $primary) {
498:                     $blob .= "\n" . $results[0] . "\n";
499:                     $primary = $results[0];
500:                 }
501:                 if (isset($results[1])) {
502:                     $blob .= "<tab>" . $results[1] . "\n";
503:                 }
504:             }
505:             $count = count($data);
506:             $msg = $this->text->makeBlob("Implant Designer Require $ability ($slot) ($count)", $blob);
507:         }
508: 
509:         $sendto->reply($msg);
510:     }
511:     
512:     /**
513:      * @HandlesCommand("implantdesigner")
514:      * @Matches("/^implantdesigner (result|results)$/i")
515:      */
516:     public function implantdesignerResultCommand($message, $channel, $sender, $sendto, $args) {
517:         $blob = $this->getImplantDesignerResults($sender);
518:         
519:         $msg = $this->text->makeBlob("Implant Designer Results", $blob);
520: 
521:         $sendto->reply($msg);
522:     }
523:     
524:     public function getImplantDesignerResults($name) {
525:         $design = $this->getDesign($name, '@');
526:         
527:         $mods = array();
528:         $reqs = array('Treatment' => 0, 'Level' => 1);  // force treatment and level to be shown first
529:         $implants = array();
530:         $clusters = array();
531:         
532:         forEach ($this->slots as $slot) {
533:             $slotObj = $design->$slot;
534:             
535:             // skip empty slots
536:             if (empty($slotObj)) {
537:                 continue;
538:             }
539:             
540:             if (!empty($slotObj->symb)) {
541:                 $symb = $slotObj->symb;
542:                 
543:                 // add reqs
544:                 if ($symb->Treatment > $reqs['Treatment']) {
545:                     $reqs['Treatment'] = $symb->Treatment;
546:                 }
547:                 if ($symb->Level > $reqs['Level']) {
548:                     $reqs['Level'] = $symb->Level;
549:                 }
550:                 forEach ($symb->reqs as $req) {
551:                     if ($req->Amount > $reqs[$req->Name]) {
552:                         $reqs[$req->Name] = $req->Amount;
553:                     }
554:                 }
555:                 
556:                 // add mods
557:                 forEach ($symb->mods as $mod) {
558:                     $mods[$mod->Name] += $mod->Amount;
559:                 }
560:                 
561:             } else {
562:                 $ql = 300;
563:                 if (!empty($slotObj->ql)) {
564:                     $ql = $slotObj->ql;
565:                 }
566:                 
567:                 // add reqs
568:                 $implant = $this->getImplantInfo($ql, $slotObj->shiny, $slotObj->bright, $slotObj->faded);
569:                 if ($implant->Treatment > $reqs['Treatment']) {
570:                     $reqs['Treatment'] = $implant->Treatment;
571:                 }
572:                 if ($implant->Ability > $reqs[$implant->AbilityName]) {
573:                     $reqs[$implant->AbilityName] = $implant->Ability;
574:                 }
575:                 
576:                 // add implant
577:                 $obj = new stdClass;
578:                 $obj->ql = $ql;
579:                 $obj->slot = $slot;
580:                 $implants []= $obj;
581:                 
582:                 // add mods
583:                 forEach ($this->grades as $grade) {
584:                     if (!empty($slotObj->$grade)) {
585:                         $effectTypeIdName = ucfirst(strtolower($grade)) . 'EffectTypeID';
586:                         $effectId = $implant->$effectTypeIdName;
587:                         $mods[$slotObj->$grade] += $this->getClusterModAmount($ql, $grade, $effectId);
588:                         
589:                         // add cluster
590:                         $obj = new stdClass;
591:                         $obj->ql = $this->implantController->getClusterMinQl($ql, $grade);
592:                         $obj->slot = $slot;
593:                         $obj->grade = $grade;
594:                         $obj->name = $slotObj->$grade;
595:                         $clusters []= $obj;
596:                     }
597:                 }
598:             }
599:         }
600:         
601:         // sort mods by name alphabetically
602:         ksort($mods);
603:         
604:         // sort clusters by name alphabetically, and then by grade, shiny first
605:         $grades = $this->grades;
606:         usort($clusters, function($cluster1, $cluster2) use($grades) {
607:             $val = strcmp($cluster1->name, $cluster2->name);
608:             if ($val == 0) {
609:                 $val1 = array_search($cluster1->grade, $grades);
610:                 $val2 = array_search($cluster2->grade, $grades);
611:                 return $val1 > $val2;
612:             } else {
613:                 return $val > 0;
614:             }
615:         });
616:         
617:         $blob .= $this->text->makeChatcmd("See Build", "/tell <myname> implantdesigner");
618:         $blob .= "\n---------\n\n";
619:         
620:         $blob .= "<header2>Requirements to Equip<end>\n";
621:         forEach ($reqs as $requirement => $amount) {
622:             $blob .= "$requirement: <highlight>$amount<end>\n";
623:         }
624:         $blob .= "\n";
625:         
626:         $blob .= "<header2>Skills Gained<end>\n";
627:         forEach ($mods as $skill => $amount) {
628:             $blob .= "$skill: <highlight>$amount<end>\n";
629:         }
630:         $blob .= "\n";
631:         
632:         $blob .= "<header2>Basic Implants Needed<end>\n";
633:         forEach ($implants as $implant) {
634:             $blob .= "<highlight>$implant->slot<end> ($implant->ql)\n";
635:         }
636:         $blob .= "\n";
637:         
638:         $blob .= "<header2>Clusters Needed<end>\n";
639:         forEach ($clusters as $cluster) {
640:             $blob .= "<highlight>{$cluster->name}<end>, {$cluster->grade} ({$cluster->ql}+)\n";
641:         }
642:         
643:         return $blob;
644:     }
645:     
646:     public function getImplantInfo($ql, $shiny, $bright, $faded) {
647:         $shiny = empty($shiny) ? '' : $shiny;
648:         $bright = empty($bright) ? '' : $bright;
649:         $faded = empty($faded) ? '' : $faded;
650: 
651:         $sql = 
652:             "SELECT
653:                 i.AbilityQL1,
654:                 i.AbilityQL200,
655:                 i.AbilityQL201,
656:                 i.AbilityQL300,
657:                 i.TreatQL1,
658:                 i.TreatQL200,
659:                 i.TreatQL201,
660:                 i.TreatQL300,
661:                 c1.EffectTypeID as ShinyEffectTypeID,
662:                 c2.EffectTypeID as BrightEffectTypeID,
663:                 c3.EffectTypeID as FadedEffectTypeID,
664:                 a.Name AS AbilityName
665:             FROM
666:                 ImplantMatrix i
667:                 JOIN Cluster c1
668:                     ON i.ShiningID = c1.ClusterID
669:                 JOIN Cluster c2
670:                     ON i.BrightID = c2.ClusterID
671:                 JOIN Cluster c3
672:                     ON i.FadedID = c3.ClusterID
673:                 JOIN Ability a
674:                     ON i.AbilityID = a.AbilityID
675:             WHERE
676:                 c1.LongName = ?
677:                 AND c2.LongName = ?
678:                 AND c3.LongName = ?";
679: 
680:         $row = $this->db->queryRow($sql, $shiny, $bright, $faded);
681:         if ($row === null) {
682:             return null;
683:         } else {
684:             return $this->addImplantInfo($row, $ql);
685:         }
686:     }
687:     
688:     private function addImplantInfo($implantInfo, $ql) {
689:         if ($ql < 201) {
690:             $minAbility = $implantInfo->AbilityQL1;
691:             $maxAbility = $implantInfo->AbilityQL200;
692:             $minTreatment = $implantInfo->TreatQL1;
693:             $maxTreatment = $implantInfo->TreatQL200;
694:             $minQl = 1;
695:             $maxQl = 200;
696:         } else {
697:             $minAbility = $implantInfo->AbilityQL201;
698:             $maxAbility = $implantInfo->AbilityQL300;
699:             $minTreatment = $implantInfo->TreatQL201;
700:             $maxTreatment = $implantInfo->TreatQL300;
701:             $minQl = 201;
702:             $maxQl = 300;
703:         }
704:         
705:         $implantInfo->Ability = $this->util->interpolate($minQl, $maxQl, $minAbility, $maxAbility, $ql);
706:         $implantInfo->Treatment = $this->util->interpolate($minQl, $maxQl, $minTreatment, $maxTreatment, $ql);
707:         
708:         return $implantInfo;
709:     }
710:     
711:     public function getClustersForSlot($implantType, $clusterType) {
712:         $sql = 
713:             "SELECT
714:                 LongName AS skill
715:             FROM
716:                 Cluster c1
717:                 JOIN ClusterImplantMap c2
718:                     ON c1.ClusterID = c2.ClusterID
719:                 JOIN ClusterType c3
720:                     ON c2.ClusterTypeID = c3.ClusterTypeID
721:                 JOIN ImplantType i
722:                     ON c2.ImplantTypeID = i.ImplantTypeID
723:             WHERE
724:                 i.ShortName = ?
725:                 AND c3.Name = ?";
726:                 
727:         return $this->db->query($sql, strtolower($implantType), strtolower($clusterType));
728:     }
729: 
730:     public function getDesign($sender, $name) {
731:         $sql = "SELECT * FROM implant_design WHERE owner = ? AND name = ?";
732:         $row = $this->db->queryRow($sql, $sender, $name);
733:         if ($row === null) {
734:             return new stdClass;
735:         } else {
736:             return json_decode($row->design);
737:         }
738:     }
739:     
740:     public function saveDesign($sender, $name, $design) {
741:         $json = json_encode($design);
742:         $sql = "UPDATE implant_design SET design = ?, dt = ? WHERE owner = ? AND name = ?";
743:         $numRows = $this->db->exec($sql, $json, time(), $sender, $name);
744:         if ($numRows == 0) {
745:             $sql = "INSERT INTO implant_design (name, owner, dt, design) VALUES (?, ?, ?, ?)";
746:             $this->db->exec($sql, $name, $sender, time(), $json);
747:         }
748:     }
749: }
750: 
Budabot 4 Docs API documentation generated by ApiGen