diff --git a/includes/basetype.class.php b/includes/basetype.class.php index 1b84f07d..66802309 100644 --- a/includes/basetype.class.php +++ b/includes/basetype.class.php @@ -552,7 +552,8 @@ trait spawnHelper private $spawnResult = array( SPAWNINFO_FULL => null, SPAWNINFO_SHORT => null, - SPAWNINFO_ZONES => null + SPAWNINFO_ZONES => null, + SPAWNINFO_QUEST => null ); private function createShortSpawns() // [zoneId, floor, [[x1, y1], [x2, y2], ..]] as tooltip2 if enabled by or anchor #map (one area, one floor, one creature, no survivors) @@ -675,9 +676,41 @@ trait spawnHelper $this->spawnResult[SPAWNINFO_ZONES] = $res; } + private function createQuestSpawns() // [zoneId => [floor => [[x1, y1], [x2, y2], ..]]] + { + if (self::$type == TYPE_SOUND) + return; + + $res = DB::Aowow()->select('SELECT areaId, floor, typeId, posX, posY FROM ?_spawns WHERE type = ?d && typeId IN (?a)', self::$type, $this->getFoundIDs()); + $spawns = []; + foreach ($res as $data) + { + // zone => floor => spawnData + // todo (low): why is there a single set of coordinates; which one should be picked, instead of the first? gets used in ShowOnMap.buildTooltip i think + if (!isset($spawns[$data['areaId']][$data['floor']][$data['typeId']])) + { + $spawns[$data['areaId']][$data['floor']][$data['typeId']] = array( + 'type' => self::$type, + 'id' => $data['typeId'], + 'point' => '', // tbd later (start, end, requirement, sourcestart, sourceend, sourcerequirement) + 'name' => Util::localizedString($this->templates[$data['typeId']], 'name'), + 'coord' => [$data['posX'], $data['posY']], + 'coords' => [[$data['posX'], $data['posY']]], + 'objective' => 0, // tbd later (1-4 set a color; id of creature this entry gives credit for) + 'reactalliance' => $this->templates[$data['typeId']]['A'] ?: 0, + 'reacthorde' => $this->templates[$data['typeId']]['H'] ?: 0 + ); + } + else + $spawns[$data['areaId']][$data['floor']][$data['typeId']]['coords'][] = [$data['posX'], $data['posY']]; + } + + $this->spawnResult[SPAWNINFO_QUEST] = $spawns; + } + public function getSpawns($mode) { - // ony Creatures and GOs can be spawned + // only Creatures, GOs and SoundEmitters can be spawned if (!self::$type || (self::$type != TYPE_NPC && self::$type != TYPE_OBJECT && self::$type != TYPE_SOUND)) return []; @@ -698,6 +731,11 @@ trait spawnHelper $this->createZoneSpawns(); return !empty($this->spawnResult[SPAWNINFO_ZONES][$this->id]) ? $this->spawnResult[SPAWNINFO_ZONES][$this->id] : []; + case SPAWNINFO_QUEST: + if (empty($this->spawnResult[SPAWNINFO_QUEST])) + $this->createQuestSpawns(); + + return $this->spawnResult[SPAWNINFO_QUEST]; } return []; diff --git a/includes/defines.php b/includes/defines.php index 6539bd10..0a9e3812 100644 --- a/includes/defines.php +++ b/includes/defines.php @@ -29,6 +29,7 @@ define('TYPE_SOUND', 19); define('TYPE_USER', 500); define('TYPE_EMOTE', 501); define('TYPE_ENCHANTMENT', 502); +define('TYPE_AREATRIGGER', 503); // not for display, but indexing in ?_spawns-table define('CACHE_TYPE_NONE', 0); // page will not be cached define('CACHE_TYPE_PAGE', 1); @@ -195,6 +196,7 @@ define('ACHIEVEMENTINFO_PROFILE', 0x1); define('SPAWNINFO_ZONES', 1); // not a mask, mutually exclusive define('SPAWNINFO_SHORT', 2); define('SPAWNINFO_FULL', 3); +define('SPAWNINFO_QUEST', 4); // Community Content define('CC_FLAG_STICKY', 0x1); diff --git a/includes/shared.php b/includes/shared.php index 9e7a7a88..8af8fe6b 100644 --- a/includes/shared.php +++ b/includes/shared.php @@ -1,6 +1,6 @@ 'Book.css']]; + protected $js = ['ShowOnMap.js']; public function __construct($pageCall, $id) { @@ -347,7 +348,8 @@ class QuestPage extends GenericPage $this->providedItem = []; // gather ids for lookup - $olItems = $olNPCs = $olGOs = $olFactions = []; + $olItems = $olNPCs = $olGOs = $olFactions = []; + $olItemData = $olNPCData = $olGOData = null; // items $olItems[0] = array( // srcItem on idx:0 @@ -459,7 +461,7 @@ class QuestPage extends GenericPage $olGOData = new GameObjectList(array(['id', $ids])); $this->extendGlobalData($olGOData->getJSGlobals(GLOBALINFO_SELF)); - foreach ($olNPCs as $i => $pair) + foreach ($olGOs as $i => $pair) { if (!$i || !in_array($i, $olGOData->getFoundIDs())) continue; @@ -531,17 +533,331 @@ class QuestPage extends GenericPage $this->addJS('?data=zones&locale='.User::$localeId.'&t='.$_SESSION['dataKey']); - /* - TODO (GODDAMNIT): jeez.. - */ + // gather points of interest + $mapNPCs = $mapGOs = []; // [typeId, start|end|objective, startItemId] - // $startend + reqNpcOrGo[1-4] + // todo (med): this double list creation very much sucks ... + $getItemSource = function ($itemId, $method = 0) use (&$mapNPCs, &$mapGOs) + { + $lootTabs = new Loot(); + if ($lootTabs->getByItem($itemId)) + { + /* + todo (med): sanity check: + there are loot templates that are absolute tosh, containing hundrets of random items (e.g. Peacebloom for Quest "The Horde Needs Peacebloom!") + even without these .. consider quests like "A Donation of Runecloth" .. oh my ..... + should we... + .. display only a maximum of sources? + .. filter sources for low drop chance? + + for the moment: + if an item has >10 sources, only display sources with >90% chance + always filter sources with <1% chance + */ + + $nSources = 0; + foreach ($lootTabs->iterate() as list($type, $data)) + if ($type == 'creature' || $type == 'object') + $nSources += count(array_filter($data['data'], function($val) { return $val['percent'] >= 1.0; })); + + foreach ($lootTabs->iterate() as $idx => list($file, $tabData)) + { + if (!$tabData['data']) + continue; + + foreach ($tabData['data'] as $data) + { + if ($data['percent'] < 1.0) + continue; + + if ($nSources > 10 && $data['percent'] < 90.0) + continue; + + switch ($file) + { + case 'creature': + $mapNPCs[] = [$data['id'], $method, $itemId]; + break; + case 'object': + $mapGOs[] = [$data['id'], $method, $itemId]; + break; + default: + break; + } + } + } + } + + // also there's vendors... + // dear god, if you are one of the types who puts queststarter-items in container-items, in conatiner-items, in container-items, in container-GOs .. you should kill yourself by killing yourself! + // so yeah .. no recursion checking + $vendors = DB::World()->selectCol(' + SELECT nv.entry FROM npc_vendor nv WHERE nv.item = ?d UNION + SELECT c.id FROM game_event_npc_vendor genv JOIN creature c ON c.guid = genv.guid WHERE genv.item = ?d', + $itemId, $itemId + ); + foreach ($vendors as $v) + $mapNPCs[] = [$v, $method, $itemId]; + }; + + $addObjectiveSpawns = function (array $spawns, callable $processing) use (&$mObjectives) + { + foreach ($spawns as $zoneId => $zoneData) + { + if (!isset($mObjectives[$zoneId])) + $mObjectives[$zoneId] = array( + 'zone' => 'Zone #'.$zoneId, + 'mappable' => 1, + 'levels' => [] + ); + + foreach ($zoneData as $floor => $floorData) + { + if (!isset($mObjectives[$zoneId]['levels'][$floor])) + $mObjectives[$zoneId]['levels'][$floor] = []; + + foreach ($floorData as $objId => $objData) + $mObjectives[$zoneId]['levels'][$floor][] = $processing($objId, $objData); + } + } + }; + + + // POI: start + end + foreach ($startEnd as $se) + { + if ($se['type'] == TYPE_NPC) + $mapNPCs[] = [$se['typeId'], $se['method'], 0]; + else if ($se['type'] == TYPE_OBJECT) + $mapGOs[] = [$se['typeId'], $se['method'], 0]; + else if ($se['type'] == TYPE_ITEM) + $getItemSource($se['typeId'], $se['method']); + } + + $itemObjectives = []; + $mObjectives = []; + $mZones = []; + $objectiveIdx = 0; + + // POI objectives + // also map olItems to objectiveIdx so every container gets the same pin color + foreach ($olItems as $i => list($itemId, $qty, $provided)) + { + if (!$provided && $itemId) + { + $itemObjectives[$itemId] = $objectiveIdx++; + $getItemSource($itemId); + } + } + + // PSA: 'redundant' data is on purpose (e.g. creature required for kill, also dropps item required to collect) + + // external event / areatrigger + if ($_specialFlags & QUEST_FLAG_SPECIAL_EXT_COMPLETE) + { + if ($atir = DB::World()->selectCell('SELECT id FROM areatrigger_involvedrelation WHERE quest = ?d', $this->typeId)) + if ($atsp = DB::AoWoW()->selectRow('SELECT guid, posX, posY, floor, areaId FROM ?_spawns WHERE `type` = ?d AND `typeId` = ?d', TYPE_AREATRIGGER, $atir)) + $mObjectives[$atsp['areaId']] = array( + 'zone' => 'Zone #'.$atsp['areaId'], + 'mappable' => 1, + 'levels' => array ( + $atsp['floor'] => array ( + array ( + 'type' => -1, // TYPE_AREATRIGGER is internal, the javascript doesn't know it + 'point' => 'requirement', + 'name' => $this->subject->parseText('end', false), + 'coord' => [$atsp['posX'], $atsp['posY']], + 'coords' => [[$atsp['posX'], $atsp['posY']]], + 'objective' => $objectiveIdx++ + ) + ) + ) + ); + } + + // ..adding creature kill requirements + if ($olNPCData && !$olNPCData->error) + { + $spawns = $olNPCData->getSpawns(SPAWNINFO_QUEST); + $addObjectiveSpawns($spawns, function ($npcId, $npcData) use ($olNPCs, &$objectiveIdx) + { + $npcData['point'] = 'requirement'; // always requirement + foreach ($olNPCs as $proxyNpcId => $npc) + { + if (empty($npc[2][$npcId])) + continue; + + $npcData['objective'] = $proxyNpcId; + break; + } + + if (!$npcData['objective']) + $npcData['objective'] = $objectiveIdx++; + + return $npcData; + }); + } + + // ..adding object interaction requirements + if ($olGOData && !$olGOData->error) + { + $spawns = $olGOData->getSpawns(SPAWNINFO_QUEST); + $addObjectiveSpawns($spawns, function ($goId, $goData, &$objectiveIdx) + { + $goData['point'] = 'requirement'; // always requirement + $goData['objective'] = $objectiveIdx++; + return $goData; + }); + } + + // .. adding npc from: droping queststart item; dropping item needed to collect; starting quest; ending quest + if ($mapNPCs) + { + $npcs = new CreatureList(array(['id', array_column($mapNPCs, 0)])); + if (!$npcs->error) + { + $startEndDupe = []; // if quest starter/ender is the same creature, we need to add it twice + $spawns = $npcs->getSpawns(SPAWNINFO_QUEST); + $addObjectiveSpawns($spawns, function ($npcId, $npcData) use ($mapNPCs, &$startEndDupe, $itemObjectives) + { + foreach ($mapNPCs as $mn) + { + if ($mn[0] != $npcId) + continue; + + if ($mn[2]) // source for itemId + $npcData['item'] = ItemList::getName($mn[2]); + + switch ($mn[1]) // method + { + case 1: // quest start + $npcData['point'] = $mn[2] ? 'sourcestart' : 'start'; + break; + case 2: // quest end (sourceend doesn't actually make sense .. oh well....) + $npcData['point'] = $mn[2] ? 'sourceend' : 'end'; + break; + case 3: // quest start & end + $npcData['point'] = $mn[2] ? 'sourcestart' : 'start'; + $startEndDupe = $npcData; + $startEndDupe['point'] = $mn[2] ? 'sourceend' : 'end'; + break; + default: // just something to kill for quest + $npcData['point'] = $mn[2] ? 'sourcerequirement' : 'requirement'; + if ($mn[2] && !empty($itemObjectives[$mn[2]])) + $npcData['objective'] = $itemObjectives[$mn[2]]; + } + } + + return $npcData; + }); + + if ($startEndDupe) + foreach ($spawns as $zoneId => $zoneData) + foreach ($zoneData as $floor => $floorData) + foreach ($floorData as $objId => $objData) + if ($objId == $startEndDupe['id']) + { + $mObjectives[$zoneId]['levels'][$floor][] = $startEndDupe; + break 3; + } + } + } + + // .. adding go from: containing queststart item; containing item needed to collect; starting quest; ending quest + if ($mapGOs) + { + $gos = new GameObjectList(array(['id', array_column($mapGOs, 0)])); + if (!$gos->error) + { + $startEndDupe = []; // if quest starter/ender is the same object, we need to add it twice + $spawns = $gos->getSpawns(SPAWNINFO_QUEST); + $addObjectiveSpawns($spawns, function ($goId, $goData) use ($mapGOs, &$startEndDupe, $itemObjectives) + { + foreach ($mapGOs as $mgo) + { + if ($mgo[0] != $goId) + continue; + + if ($mgo[2]) // source for itemId + $goData['item'] = ItemList::getName($mgo[2]); + + switch ($mgo[1]) // method + { + case 1: // quest start + $goData['point'] = $mgo[2] ? 'sourcestart' : 'start'; + break; + case 2: // quest end (sourceend doesn't actually make sense .. oh well....) + $goData['point'] = $mgo[2] ? 'sourceend' : 'end'; + break; + case 3: // quest start & end + $goData['point'] = $mgo[2] ? 'sourcestart' : 'start'; + $startEndDupe = $goData; + $startEndDupe['point'] = $mgo[2] ? 'sourceend' : 'end'; + break; + default: // just something to kill for quest + $goData['point'] = $mgo[2] ? 'sourcerequirement' : 'requirement'; + if ($mgo[2] && !empty($itemObjectives[$mgo[2]])) + $goData['objective'] = $itemObjectives[$mgo[2]]; + } + } + + return $goData; + }); + + if ($startEndDupe) + foreach ($spawns as $zoneId => $zoneData) + foreach ($zoneData as $floor => $floorData) + foreach ($floorData as $objId => $objData) + if ($objId == $startEndDupe['id']) + { + $mObjectives[$zoneId]['levels'][$floor][] = $startEndDupe; + break 3; + } + } + } + + // ..process zone data + if ($mObjectives) + { + $areas = new ZoneList(array(['id', array_keys($mObjectives)])); + if (!$areas->error) + { + $someIDX = 0; // todo (low): UNK value ... map priority, floor, mapId..? values seen: 0,3; doesn't seem to affect anything + foreach ($areas->iterate() as $id => $__) + { + $mObjectives[$id]['zone'] = $areas->getField('name', true); + $mZones[] = [$id, $someIDX]; + } + } + } + + // has start & end? + $hasStartEnd = 0x0; + foreach ($mObjectives as $levels) + { + foreach ($levels['levels'] as $floor) + { + foreach ($floor as $entry) + { + if ($entry['point'] == 'start' || $entry['point'] == 'sourcestart') + $hasStartEnd |= 0x1; + else if ($entry['point'] == 'end' || $entry['point'] == 'sourceend') + $hasStartEnd |= 0x2; + } + } + } + + $this->map = $mObjectives ? array( + 'mapperData' => [], // always empty + 'data' => array( + 'parent' => 'mapper-generic', + 'objectives' => $mObjectives, + 'zoneparent' => 'mapper-zone-generic', + 'zones' => $mZones, + 'missing' => count($mZones) > 1 || $hasStartEnd != 0x3 ? 1 : 0 // 0 if everything happens in one zone, else 1 + ) + ) : null; - $this->map = null; - // array( - // 'data' => ['zone' => $this->typeId], - // 'som' => Util::toJSON($som) - // ); /****************/ /* Main Content */ diff --git a/setup/db_structure.sql b/setup/db_structure.sql index 8f121dd4..16fd7767 100644 --- a/setup/db_structure.sql +++ b/setup/db_structure.sql @@ -1965,7 +1965,7 @@ DROP TABLE IF EXISTS `aowow_spawns`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `aowow_spawns` ( `guid` int(11) NOT NULL COMMENT '< 0: vehicle accessory', - `type` tinyint(3) unsigned NOT NULL, + `type` smallint(5) unsigned NOT NULL, `typeId` int(10) unsigned NOT NULL, `respawn` int(10) unsigned NOT NULL COMMENT 'in seconds', `spawnMask` tinyint(3) unsigned NOT NULL, diff --git a/setup/tools/dbc.class.php b/setup/tools/dbc.class.php index d42928f0..b6e3cd80 100644 --- a/setup/tools/dbc.class.php +++ b/setup/tools/dbc.class.php @@ -45,6 +45,7 @@ class DBC 'achievement_category' => 'nisxssxxsxsxxxxxxxxx', 'achievement_criteria' => 'niiiiiiiisxssxxsxsxxxxxxxxiixii', 'areatable' => 'niixixxiiixsxssxxsxsxxxxxxxxixxxxxxx', + 'areatrigger' => 'niffxxxxxx', 'battlemasterlist' => 'niixxxxxxixxxxxxxxxxxxxxxxxxixii', 'charbaseinfo' => 'bb', 'charstartoutfit' => 'nbbbXiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', @@ -145,6 +146,7 @@ class DBC 'achievement_category' => 'Id,parentCategory,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8', 'achievement_criteria' => 'Id,refAchievementId,type,value1,value2,value3,value4,value5,value6,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,completionFlags,groupFlags,timeLimit,order', 'areatable' => 'Id,mapId,areaTable,flags,soundAmbience,zoneMusic,zoneIntroMusic,name_loc0,name_loc2,name_loc3,name_loc6,name_loc8,factionGroupMask', + 'areatrigger' => 'Id,mapId,posY,posX', 'battlemasterlist' => 'Id,mapId,moreMapId,areaType,maxPlayers,minLevel,maxLevel', 'charbaseinfo' => 'raceId,classId', 'charstartoutfit' => 'Id,raceId,classId,gender,item1,item2,item3,item4,item5,item6,item7,item8,item9,item10,item11,item12,item13,item14,item15,item16,item17,item18,item19,item20', diff --git a/setup/tools/sqlgen/spawns.func.php b/setup/tools/sqlgen/spawns.func.php index 9da4dd0f..4be1fc27 100644 --- a/setup/tools/sqlgen/spawns.func.php +++ b/setup/tools/sqlgen/spawns.func.php @@ -23,7 +23,7 @@ if (!CLI) $customData = array( ); -$reqDBC = ['worldmaparea', 'map', 'dungeonmap', 'taxipathnode', 'soundemitters']; +$reqDBC = ['worldmaparea', 'map', 'dungeonmap', 'taxipathnode', 'soundemitters', 'areatrigger']; function spawns() // and waypoints { @@ -102,15 +102,19 @@ function spawns() // and waypoints 'FROM dbc_soundemitters', ' - assembling '.CLISetup::bold('sound emitter').' spawns']; - $query[4] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, w.waittime AS "wait", w.location_y AS `posX`, w.location_x AS `posY` ' . + $query[4] = ['SELECT Id AS "guid", 503 AS "type", Id AS typeId, 0 AS respawn, 0 AS phaseMask, 0 AS areaId, mapId AS "map", 0 AS pathId, posX, posY ' . + 'FROM dbc_areatrigger', + ' - assembling '.CLISetup::bold('areatrigger').' spawns']; + + $query[5] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, w.waittime AS "wait", w.location_y AS `posX`, w.location_x AS `posY` ' . 'FROM creature c JOIN script_waypoint w ON c.id = w.entry', ' - assembling waypoints from '.CLISetup::bold('script_waypoint')]; - $query[5] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, 0 AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' . + $query[6] = ['SELECT c.guid, w.entry AS "npcOrPath", w.pointId AS "point", c.zoneId AS areaId, c.map, 0 AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' . 'FROM creature c JOIN waypoints w ON c.id = w.entry', ' - assembling waypoints from '.CLISetup::bold('waypoints')]; - $query[6] = ['SELECT c.guid, -w.id AS "npcOrPath", w.point, c.zoneId AS areaId, c.map, w.delay AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' . + $query[7] = ['SELECT c.guid, -w.id AS "npcOrPath", w.point, c.zoneId AS areaId, c.map, w.delay AS "wait", w.position_y AS `posX`, w.position_x AS `posY` ' . 'FROM creature c JOIN creature_addon ca ON ca.guid = c.guid JOIN waypoint_data w ON w.id = ca.path_id WHERE ca.path_id <> 0', ' - assembling waypoints from '.CLISetup::bold('waypoint_data')]; @@ -154,7 +158,7 @@ function spawns() // and waypoints $n = 0; $sum = 0; - if ($idx == 3) + if ($idx == 3 || $idx == 4) $queryResult = DB::Aowow()->select($q[0]); else $queryResult = DB::World()->select($q[0]); @@ -183,14 +187,14 @@ function spawns() // and waypoints if (!$points) // still impossible (there are areas that are intentionally off the map (e.g. the isles south of tanaris)) { - CLISetup::log('GUID '.$spawn['guid'].($idx < 4 ? '' : ' on path/point '.$spawn['npcOrPath'].'/'.$spawn['point']).' could not be matched to displayable area [A:'.$spawn['areaId'].'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLISetup::LOG_WARN); + CLISetup::log('GUID '.$spawn['guid'].($idx < 5 ? '' : ' on path/point '.$spawn['npcOrPath'].'/'.$spawn['point']).' could not be matched to displayable area [A:'.$spawn['areaId'].'; X:'.$spawn['posY'].'; Y:'.$spawn['posX'].']', CLISetup::LOG_WARN); continue; } // if areaId is set, area was determined by TC .. we're fine .. mostly $final = $spawn['areaId'] ? $points[0] : $checkCoords($points); - if ($idx < 4) + if ($idx < 5) { $set = array( 'guid' => $spawn['guid'], diff --git a/setup/updates/1489291710_01.sql b/setup/updates/1489291710_01.sql new file mode 100644 index 00000000..ac9ccdd3 --- /dev/null +++ b/setup/updates/1489291710_01.sql @@ -0,0 +1,6 @@ +ALTER TABLE `aowow_spawns` + ALTER `type` DROP DEFAULT; +ALTER TABLE `aowow_spawns` + CHANGE COLUMN `type` `type` SMALLINT UNSIGNED NOT NULL AFTER `guid`; + +UPDATE `aowow_dbversion` SET `sql` = CONCAT(IFNULL(`sql`, ''), ' spawns'); diff --git a/static/js/global.js b/static/js/global.js index 1a4b3e1f..e29540c4 100644 --- a/static/js/global.js +++ b/static/js/global.js @@ -18385,14 +18385,14 @@ Mapper.prototype = { var maxIdx = [false, -1]; for(var i = 0; i < zoneList.length; ++i) { - if(i > 0) $WH.ae(span, (i == zoneList.length-1 ? LANG.and : LANG.comma)); + if(i > 0) $WH.ae(span, $WH.ct(i == zoneList.length-1 ? LANG.and : LANG.comma)); var entry = null; if(self.objectives[zoneList[i][0]].mappable > 0) { entry = $WH.ce('a'); entry.href = 'javascript:;'; $WH.ae(entry, $WH.ct(self.objectives[zoneList[i][0]].zone)); - entry.onClick = function(link, zone) { + entry.onclick = function(link, zone) { self.update({ zone: zone }); g_setSelectedLink(link, 'mapper'); }.bind(self, entry, zoneList[i][0]); @@ -18509,121 +18509,121 @@ Mapper.prototype = { var parts = LANG.mapper_happensin.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, zones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); } else if(startEnd && types.objective.length == 0) // starts and ends in x { var parts = LANG.mapper_objectives.sex.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, zones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); } else if(startEnd) // objectives in x, starts and ends in y { var parts = LANG.mapper_objectives.ox_sey.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, startZones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); secondaryLink = zoneLinks(this, span, objZones, typesByZone); - $WH.ae(span, parts[2]); + $WH.ae(span, $WH.ct(parts[2])); } else if(startObj && types.end.length == 0) // objectives and starts in x { var parts = LANG.mapper_objectives.osx.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, zones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); } else if(startObj) // objectives and starts in x, ends in y { var parts = LANG.mapper_objectives.osx_ey.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, objZones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); secondaryLink = zoneLinks(this, span, endZones, typesByZone); - $WH.ae(span, parts[2]); + $WH.ae(span, $WH.ct(parts[2])); } else if(endObj && types.start.length == 0) // objectives and ends in x { var parts = LANG.mapper_objectives.oex.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, zones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); } else if(endObj) // objectives and ends in x, starts in y { var parts = LANG.mapper_objectives.oex_sy.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, startZones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); secondaryLink = zoneLinks(this, span, objZones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); } else if(types.start.length > 0 && types.end.length > 0 && types.objective.length > 0) // objectives in x, starts in y, ends in z { var parts = LANG.mapper_objectives.ox_sy_ez.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, startZones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); secondaryLink = zoneLinks(this, span, objZones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); tertiaryLink = zoneLinks(this, span, endZones, typesByZone); - $WH.ae(span, parts[3]); + $WH.ae(span, $WH.ct(parts[3])); } else if(types.start.length > 0 && types.end.length > 0) // starts in x, ends in y { var parts = LANG.mapper_objectives.sx_ey.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, startZones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); secondaryLink = zoneLinks(this, span, endZones, typesByZone); - $WH.ae(span, parts[2]); + $WH.ae(span, $WH.ct(parts[2])); } else if(types.start.length > 0 && types.objective.length > 0) // objectives in x, starts in y { var parts = LANG.mapper_objectives.ox_sy.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, startZones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); secondaryLink = zoneLinks(this, span, objZones, typesByZone); - $WH.ae(span, parts[2]); + $WH.ae(span, $WH.ct(parts[2])); } else if(types.end.length > 0 && types.objective.length > 0) // objectives in x, ends in y { var parts = LANG.mapper_objectives.ox_ey.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, objZones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); secondaryLink = zoneLinks(this, span, endZones, typesByZone); - $WH.ae(span, parts[2]); + $WH.ae(span, $WH.ct(parts[2])); } else if(types.start.length > 0) // starts in x { var parts = LANG.mapper_objectives.sx.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, zones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); } else if(types.end.length > 0) // ends in x { var parts = LANG.mapper_objectives.ex.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, zones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); } else if(types.objective.length > 0) // objectives in x { var parts = LANG.mapper_objectives.ox.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, zones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); } else // wat? { var parts = LANG.mapper_happensin.split('$$'); $WH.ae(span, $WH.ct(parts[0])); primaryLink = zoneLinks(this, span, zones, typesByZone); - $WH.ae(span, parts[1]); + $WH.ae(span, $WH.ct(parts[1])); } $WH.ae(div, span); diff --git a/template/bricks/mapper.tpl.php b/template/bricks/mapper.tpl.php index 894a7540..25096e2d 100644 --- a/template/bricks/mapper.tpl.php +++ b/template/bricks/mapper.tpl.php @@ -2,8 +2,10 @@ if (isset($this->map) && empty($this->map)): echo Lang::zone('noMap'); elseif (!empty($this->map['data'])): - if ($this->type != TYPE_ZONE): - echo '
'.($this->type == TYPE_OBJECT ? Lang::gameObject('foundIn') : ($this->type == TYPE_SOUND ? Lang::sound('foundIn') : Lang::npc('foundIn'))).' '; + if ($this->type == TYPE_QUEST) : + echo "
\n"; + elseif ($this->type != TYPE_ZONE): + echo '
'.($this->type == TYPE_OBJECT ? Lang::gameObject('foundIn') : ($this->type == TYPE_SOUND ? Lang::sound('foundIn') : Lang::npc('foundIn'))).' '; $n = count($this->map['mapperData']); $i = 0; @@ -34,10 +36,10 @@ elseif (!empty($this->map['data'])): -
map['som'])): ?> +
map['data'])): map['data']['zone'])): echo " ".(!empty($this->gPageInfo) ? "$.extend(g_pageInfo, {id: ".$this->map['data']['zone']."})" : "var g_pageInfo = {id: ".$this->map['data']['zone']."}").";\n"; - elseif (!empty($this->map['mapperData'])): - echo " var g_mapperData = ".Util::toJSON($this->map['mapperData']).";\n"; + elseif (isset($this->map['mapperData'])): + echo " var g_mapperData = ".Util::toJSON($this->map['mapperData'], empty($this->map['mapperData']) ? JSON_FORCE_OBJECT : 0).";\n"; endif; // dont forget to set "parent: 'mapper-generic'" @@ -63,8 +65,8 @@ elseif (!empty($this->map['data'])): echo " new ShowOnMap(".Util::toJSON($this->map['som']).");\n"; endif; - if ($this->type != TYPE_ZONE): - echo " \$WH.gE(\$WH.ge('locations'), 'a')[0].onclick();\n"; + if ($this->type != TYPE_ZONE && $this->type != TYPE_QUEST): + echo " \$WH.gE(\$WH.ge('mapper-zone-generic'), 'a')[0].onclick();\n"; endif; ?> //]]>