mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
SmartAI/Conditions
* embed Conditions into SmartAI table so we can evaluate CONDITION_SOURCE_TYPE_SMART_EVENT (22) * make SmartAI table display flexible
This commit is contained in:
@@ -105,7 +105,7 @@ class AreatriggerBaseResponse extends TemplateResponse implements ICache
|
||||
|
||||
// tab: conditions
|
||||
$cnd = new Conditions();
|
||||
$cnd->getBySourceEntry($this->typeId, Conditions::SRC_AREATRIGGER_CLIENT)->prepare();
|
||||
$cnd->getBySource(Conditions::SRC_AREATRIGGER_CLIENT, entry: $this->typeId)->prepare();
|
||||
if ($tab = $cnd->toListviewTab())
|
||||
{
|
||||
$this->extendGlobalData($cnd->getJsGlobals());
|
||||
|
||||
@@ -734,7 +734,7 @@ class ItemBaseResponse extends TemplateResponse implements ICache
|
||||
$extraCols = ['$Listview.extraCols.stock', "\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", '$Listview.extraCols.cost'];
|
||||
|
||||
$cnd = new Conditions();
|
||||
$cnd->getBySourceEntry($this->typeId, Conditions::SRC_NPC_VENDOR)->prepare();
|
||||
$cnd->getBySource(Conditions::SRC_NPC_VENDOR, entry: $this->typeId)->prepare();
|
||||
foreach ($sbData as $k => &$row)
|
||||
{
|
||||
$currency = [];
|
||||
|
||||
@@ -385,7 +385,7 @@ class NpcBaseResponse extends TemplateResponse implements ICache
|
||||
}
|
||||
|
||||
$cnd = new Conditions();
|
||||
$cnd->getBySourceGroup($this->typeId, Conditions::SRC_VEHICLE_SPELL)->prepare();
|
||||
$cnd->getBySource(Conditions::SRC_VEHICLE_SPELL, group: $this->typeId)->prepare();
|
||||
if ($cnd->toListviewColumn($controled, $extraCols, $this->typeId, 'id'))
|
||||
$this->extendGlobalData($cnd->getJsGlobals());
|
||||
|
||||
@@ -547,7 +547,7 @@ class NpcBaseResponse extends TemplateResponse implements ICache
|
||||
}
|
||||
|
||||
$cnd = new Conditions();
|
||||
if ($cnd->getBySourceGroup($this->typeId, Conditions::SRC_NPC_VENDOR)->prepare())
|
||||
if ($cnd->getBySource(Conditions::SRC_NPC_VENDOR, group: $this->typeId)->prepare())
|
||||
{
|
||||
$this->extendGlobalData($cnd->getJsGlobals());
|
||||
$cnd->toListviewColumn($lvData, $extraCols, $this->typeId, 'id');
|
||||
@@ -805,8 +805,8 @@ class NpcBaseResponse extends TemplateResponse implements ICache
|
||||
|
||||
// tab: conditions
|
||||
$cnd = new Conditions();
|
||||
$cnd->getBySourceEntry($this->typeId, Conditions::SRC_CREATURE_TEMPLATE_VEHICLE)
|
||||
->getBySourceGroup($this->typeId, Conditions::SRC_SPELL_CLICK_EVENT)
|
||||
$cnd->getBySource(Conditions::SRC_CREATURE_TEMPLATE_VEHICLE, entry: $this->typeId)
|
||||
->getBySource(Conditions::SRC_SPELL_CLICK_EVENT, group: $this->typeId)
|
||||
->getByCondition(Type::NPC, $this->typeId)
|
||||
->prepare();
|
||||
if ($tab = $cnd->toListviewTab())
|
||||
|
||||
@@ -979,7 +979,7 @@ class QuestBaseResponse extends TemplateResponse implements ICache
|
||||
|
||||
// tab: conditions
|
||||
$cnd = new Conditions();
|
||||
$cnd->getBySourceEntry($this->typeId, Conditions::SRC_QUEST_AVAILABLE, Conditions::SRC_QUEST_SHOW_MARK)
|
||||
$cnd->getBySource([Conditions::SRC_QUEST_AVAILABLE, Conditions::SRC_QUEST_SHOW_MARK], entry: $this->typeId)
|
||||
->getByCondition(Type::QUEST, $this->typeId)
|
||||
->prepare();
|
||||
|
||||
|
||||
@@ -1210,7 +1210,7 @@ class SpellBaseResponse extends TemplateResponse implements ICache
|
||||
|
||||
// tab: conditions
|
||||
$cnd = new Conditions();
|
||||
$cnd->getBySourceEntry($this->typeId, Conditions::SRC_SPELL_IMPLICIT_TARGET, Conditions::SRC_SPELL, Conditions::SRC_SPELL_CLICK_EVENT, Conditions::SRC_VEHICLE_SPELL, Conditions::SRC_SPELL_PROC)
|
||||
$cnd->getBySource([Conditions::SRC_SPELL_IMPLICIT_TARGET, Conditions::SRC_SPELL, Conditions::SRC_SPELL_CLICK_EVENT, Conditions::SRC_VEHICLE_SPELL, Conditions::SRC_SPELL_PROC], entry: $this->typeId)
|
||||
->getByCondition(Type::SPELL, $this->typeId)
|
||||
->prepare();
|
||||
if ($tab = $cnd->toListviewTab())
|
||||
|
||||
@@ -221,29 +221,26 @@ class Conditions
|
||||
/* IN */
|
||||
/******/
|
||||
|
||||
public function getBySourceEntry(int $entry, int ...$srcType) : self
|
||||
public function getBySource(int|array $type, int|array $group = 0, int|array $entry = 0, int|array $id = 0) : self
|
||||
{
|
||||
if ($group)
|
||||
$group = is_int($group) ? [$group] : array_map('intVal', $group);
|
||||
if ($entry)
|
||||
$entry = is_int($entry) ? [$entry] : array_map('intVal', $entry);
|
||||
if ($id)
|
||||
$id = is_int($id) ? [$id] : array_map('intVal', $id);
|
||||
if ($type)
|
||||
$type = is_int($type) ? [$type] : array_map('intVal', $type);
|
||||
else
|
||||
return $this;
|
||||
|
||||
$this->rows = array_merge($this->rows, DB::World()->select(
|
||||
'SELECT `SourceTypeOrReferenceId`, `SourceEntry`, `SourceGroup`, `SourceId`, `ElseGroup`,
|
||||
`ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`
|
||||
FROM conditions
|
||||
WHERE `SourceTypeOrReferenceId` IN (?a) AND `SourceEntry` = ?d
|
||||
WHERE `SourceTypeOrReferenceId` IN (?a){ AND `SourceGroup` IN (?a)}{ AND `SourceEntry` IN (?a)}{ AND `SourceId` IN (?a)}
|
||||
ORDER BY `SourceTypeOrReferenceId`, `SourceEntry`, `SourceGroup`, `ElseGroup` ASC',
|
||||
$srcType, $entry
|
||||
));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBySourceGroup(int $group, int ...$srcType) : self
|
||||
{
|
||||
$this->rows = array_merge($this->rows, DB::World()->select(
|
||||
'SELECT `SourceTypeOrReferenceId`, `SourceEntry`, `SourceGroup`, `SourceId`, `ElseGroup`,
|
||||
`ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`
|
||||
FROM conditions
|
||||
WHERE `SourceTypeOrReferenceId` IN (?a) AND `SourceGroup` = ?d
|
||||
ORDER BY `SourceTypeOrReferenceId`, `SourceEntry`, `SourceGroup`, `ElseGroup` ASC',
|
||||
$srcType, $group
|
||||
$type, $group ?: DBSIMPLE_SKIP, $entry ?: DBSIMPLE_SKIP, $id ?: DBSIMPLE_SKIP
|
||||
));
|
||||
|
||||
return $this;
|
||||
@@ -386,6 +383,14 @@ class Conditions
|
||||
return $success;
|
||||
}
|
||||
|
||||
public function toMarkupTag() : string
|
||||
{
|
||||
if (!$this->result)
|
||||
return '';
|
||||
|
||||
return '[condition]' . json_encode($this->result, JSON_NUMERIC_CHECK) . '[/condition]';
|
||||
}
|
||||
|
||||
public function getJsGlobals() : array
|
||||
{
|
||||
return $this->jsGlobals;
|
||||
@@ -486,9 +491,9 @@ class Conditions
|
||||
$this->jsGlobals[$grp][$sGroup] = $sGroup;
|
||||
if (is_int($entry))
|
||||
$this->jsGlobals[$entry][$sEntry] = $sEntry;
|
||||
// Note: sourceId currently has no typed content
|
||||
// if (is_int($id))
|
||||
// $this->jsGlobals[$id][$sId] = $sId;
|
||||
// Note: sourceId currently has no typed content
|
||||
// if (is_int($id))
|
||||
// $this->jsGlobals[$id][$sId] = $sId;
|
||||
|
||||
// more checks? not all sources can retarget
|
||||
$cTarget = min(1, max(0, $cTarget));
|
||||
|
||||
@@ -257,8 +257,16 @@ class SmartAI
|
||||
private array $result = [];
|
||||
private array $tabs = [];
|
||||
private array $itr = [];
|
||||
private array $quotes = [];
|
||||
|
||||
private array $quotes = [];
|
||||
public string $css = <<<CSS
|
||||
#smartai-generic .grid { clear:left; display: grid; }
|
||||
#smartai-generic .tabbed-contents { padding:0px; clear:left; }
|
||||
#smartai-generic .grid thead,
|
||||
#smartai-generic .grid tbody,
|
||||
#smartai-generic .grid tr { display: contents; }
|
||||
#sai { display: grid; }
|
||||
CSS;
|
||||
|
||||
// misc data
|
||||
public readonly int $baseEntry; // I'm a timed action list belonging to this entry
|
||||
@@ -271,24 +279,28 @@ class SmartAI
|
||||
$this->title = $miscData['title'] ?? '';
|
||||
$this->teleportTargetArea = $miscData['teleportTargetArea'] ?? 0;
|
||||
|
||||
if ($this->baseEntry) // my parent handles base css
|
||||
$this->css = '';
|
||||
|
||||
$raw = DB::World()->select(
|
||||
'SELECT `id`, `link`,
|
||||
`event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`,
|
||||
`action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`,
|
||||
`target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`
|
||||
FROM smart_scripts
|
||||
WHERE `entryorguid` = ?d AND `source_type` = ?d
|
||||
ORDER BY `id` ASC',
|
||||
'SELECT `id`, `link`,
|
||||
`event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`,
|
||||
`action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`,
|
||||
`target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`
|
||||
FROM smart_scripts
|
||||
WHERE `entryorguid` = ?d AND `source_type` = ?d
|
||||
ORDER BY `id` ASC',
|
||||
$this->entry, $this->srcType);
|
||||
|
||||
foreach ($raw as $r)
|
||||
{
|
||||
$this->rawData[$r['id']] = array(
|
||||
'id' => $r['id'],
|
||||
'link' => $r['link'],
|
||||
'event' => new SmartEvent($r['id'], $r['event_type'], $r['event_phase_mask'], $r['event_chance'], $r['event_flags'], [$r['event_param1'], $r['event_param2'], $r['event_param3'], $r['event_param4'], $r['event_param5']], $this),
|
||||
'action' => new SmartAction($r['id'], $r['action_type'], [$r['action_param1'], $r['action_param2'], $r['action_param3'], $r['action_param4'], $r['action_param5'], $r['action_param6']], $this),
|
||||
'target' => new SmartTarget($r['id'], $r['target_type'], [$r['target_param1'], $r['target_param2'], $r['target_param3'], $r['target_param4']], [$r['target_x'], $r['target_y'], $r['target_z'], $r['target_o']], $this)
|
||||
'id' => $r['id'],
|
||||
'link' => $r['link'],
|
||||
'event' => new SmartEvent($r['id'], $r['event_type'], $r['event_phase_mask'], $r['event_chance'], $r['event_flags'], [$r['event_param1'], $r['event_param2'], $r['event_param3'], $r['event_param4'], $r['event_param5']], $this),
|
||||
'action' => new SmartAction($r['id'], $r['action_type'], [$r['action_param1'], $r['action_param2'], $r['action_param3'], $r['action_param4'], $r['action_param5'], $r['action_param6']], $this),
|
||||
'target' => new SmartTarget($r['id'], $r['target_type'], [$r['target_param1'], $r['target_param2'], $r['target_param3'], $r['target_param4']], [$r['target_x'], $r['target_y'], $r['target_z'], $r['target_o']], $this),
|
||||
'condition' => (new Conditions())->getBySource(Conditions::SRC_SMART_EVENT, $r['id'] + 1, $entry, $srcType)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -619,10 +631,9 @@ class SmartAI
|
||||
if ($this->result)
|
||||
return true;
|
||||
|
||||
$hidePhase =
|
||||
$hideChance = true;
|
||||
$visibleCols = (1 << 0) | (1 << 2) | (1 << 4);
|
||||
|
||||
foreach ($this->iterate() as $id => $__)
|
||||
foreach ($this->iterate() as $__)
|
||||
{
|
||||
$rowIdx = Util::createHash(8);
|
||||
|
||||
@@ -636,53 +647,60 @@ class SmartAI
|
||||
$evtBody = str_replace(['#target#', '#rowIdx#'], [$this->itr['target']->process(), $rowIdx], $evtBody);
|
||||
$actBody = str_replace(['#target#', '#rowIdx#'], [$this->itr['target']->process(), $rowIdx], $actBody);
|
||||
|
||||
if (!$this->itr['event']->hasPhases())
|
||||
$hidePhase = false;
|
||||
if ($this->itr['event']->hasPhases())
|
||||
$visibleCols |= (1 << 1);
|
||||
|
||||
if ($this->itr['event']->chance != 100)
|
||||
$hideChance = false;
|
||||
$visibleCols |= (1 << 3);
|
||||
|
||||
if ($this->itr['condition']->prepare())
|
||||
{
|
||||
$visibleCols |= (1 << 5);
|
||||
Util::mergeJsGlobals($this->jsGlobals, $this->itr['condition']->getJsGlobals());
|
||||
}
|
||||
|
||||
$this->result[] = array(
|
||||
$this->itr['id'],
|
||||
implode(', ', Util::mask2bits($this->itr['event']->phaseMask, 1)),
|
||||
$evtBody.($evtFooter ? '[div float=right margin=0px clear=both][i][small class=q0]'.$evtFooter.'[/small][/i][/div]' : null),
|
||||
$evtBody.($evtFooter ? '[div float=right margin=0px clear=both width=100% align=right][i][small class=q0]'.$evtFooter.'[/small][/i][/div]' : ''),
|
||||
$this->itr['event']->chance.'%',
|
||||
$actBody.($actFooter ? '[div float=right margin=0px clear=both][i][small class=q0]'.$actFooter.'[/small][/i][/div]' : null)
|
||||
$actBody.($actFooter ? '[div float=right margin=0px clear=both width=100% align=right][i][small class=q0]'.$actFooter.'[/small][/i][/div]' : ''),
|
||||
$this->itr['condition']->toMarkupTag()
|
||||
);
|
||||
}
|
||||
|
||||
$th = array(
|
||||
'#' => 16,
|
||||
'Phase' => 32,
|
||||
'Event' => 350,
|
||||
'Chance' => 24,
|
||||
'Action' => 0
|
||||
['#' , '24px'],
|
||||
['Phase', '48px'],
|
||||
['Event', '30%%'],
|
||||
['Chance', '60px'],
|
||||
['Action', 'auto'],
|
||||
['Condition', 'auto']
|
||||
);
|
||||
|
||||
if ($hidePhase)
|
||||
for ($i = 0, $j = count($th); $i < $j; $i++)
|
||||
{
|
||||
unset($th['Phase']);
|
||||
foreach ($this->result as &$r)
|
||||
unset($r[1]);
|
||||
}
|
||||
unset($r);
|
||||
if ($visibleCols & (1 << $i))
|
||||
continue;
|
||||
|
||||
if ($hideChance)
|
||||
{
|
||||
unset($th['Chance']);
|
||||
unset($th[$i]);
|
||||
foreach ($this->result as &$r)
|
||||
unset($r[3]);
|
||||
}
|
||||
unset($r);
|
||||
unset($r[$i]);
|
||||
|
||||
$tbl = '[tr]';
|
||||
foreach ($th as $n => $w)
|
||||
$tbl .= '[td header '.($w ? 'width='.$w.'px' : null).']'.$n.'[/td]';
|
||||
$tbl .= '[/tr]';
|
||||
unset($r);
|
||||
}
|
||||
|
||||
$tblId = Util::createHash(12);
|
||||
|
||||
$this->css .= "\n#tbl-".$tblId." { grid-template-columns: ".implode(' ', array_column($th, 1))."; }";
|
||||
|
||||
$tbl = '[tr]' . array_reduce(array_column($th, 0), fn($out, $n) => $out .= '[td header]'.$n.'[/td]', '') . '[/tr]';
|
||||
|
||||
foreach ($this->result as $r)
|
||||
$tbl .= '[tr][td]'.implode('[/td][td]', $r).'[/td][/tr]';
|
||||
|
||||
$tbl = '[table id=tbl-'.$tblId.' class=grid]'.$tbl.'[/table]';
|
||||
|
||||
if ($this->srcType == self::SRC_TYPE_ACTIONLIST)
|
||||
$this->tabs[$this->entry] = $tbl;
|
||||
else
|
||||
@@ -698,16 +716,16 @@ class SmartAI
|
||||
if (!$this->rawData)
|
||||
return null;
|
||||
|
||||
$wrapper = '[table class=grid width=940px]%s[/table]';
|
||||
$return = '[style]#smartai-generic .grid { clear:left; } #smartai-generic .tabbed-contents { padding:0px; clear:left; }[/style][pad][h3][toggler id=sai]SmartAI'.$this->title.'[/toggler][/h3][div id=sai clear=left]%s[/div]';
|
||||
$wrapper = '%s';
|
||||
$return = '[style]'.strtr($this->css, "\n", ' ').'[/style][pad][h3][toggler id=sai]SmartAI'.$this->title.'[/toggler][/h3][div id=sai clear=left]%s[/div]';
|
||||
$tabs = '';
|
||||
if (count($this->tabs) > 1)
|
||||
{
|
||||
$wrapper = '[tabs name=sai width=942px]%s[/tabs]';
|
||||
$wrapper = '[tabs name=sai]%s[/tabs]';
|
||||
$return = "[script]function TalTabClick(id) { $('#dsf67g4d-sai').find('[href=\'#sai-actionlist-' + id + '\']').click(); }[/script]" . $return;
|
||||
foreach ($this->tabs as $guid => $data)
|
||||
{
|
||||
$buff = '[tab name="'.($guid ? 'ActionList #'.$guid : 'Main').'"][table class=grid width=940px]'.$data.'[/table][/tab]';
|
||||
$buff = '[tab name="'.($guid ? 'ActionList #'.$guid : 'Main').'"]'.$data.'[/tab]';
|
||||
if ($guid)
|
||||
$tabs .= $buff;
|
||||
else
|
||||
|
||||
@@ -562,6 +562,8 @@ class SmartAction
|
||||
$tal = new SmartAI(SmartAI::SRC_TYPE_ACTIONLIST, $this->param[0], ['baseEntry' => $this->smartAI->getEntry()]);
|
||||
$tal->prepare();
|
||||
|
||||
$this->smartAI->css .= $tal->css;
|
||||
|
||||
Util::mergeJsGlobals($this->jsGlobals, $tal->getJSGlobals());
|
||||
|
||||
foreach ($tal->getTabs() as $guid => $tt)
|
||||
@@ -587,6 +589,8 @@ class SmartAction
|
||||
$tal = new SmartAI(SmartAI::SRC_TYPE_ACTIONLIST, $this->param[$i], ['baseEntry' => $this->smartAI->getEntry()]);
|
||||
$tal->prepare();
|
||||
|
||||
$this->smartAI->css .= $tal->css;
|
||||
|
||||
Util::mergeJsGlobals($this->jsGlobals, $tal->getJSGlobals());
|
||||
|
||||
foreach ($tal->getTabs() as $guid => $tt)
|
||||
@@ -603,6 +607,8 @@ class SmartAction
|
||||
$tal = new SmartAI(SmartAI::SRC_TYPE_ACTIONLIST, $i, ['baseEntry' => $this->smartAI->getEntry()]);
|
||||
$tal->prepare();
|
||||
|
||||
$this->smartAI->css .= $tal->css;
|
||||
|
||||
Util::mergeJsGlobals($this->jsGlobals, $tal->getJSGlobals());
|
||||
|
||||
foreach ($tal->getTabs() as $guid => $tt)
|
||||
|
||||
@@ -368,7 +368,7 @@ class SmartEvent
|
||||
|
||||
public function hasPhases() : bool
|
||||
{
|
||||
return $this->phaseMask == 0;
|
||||
return $this->phaseMask && ($this->phaseMask & 0xFFF) != 0xFFF;
|
||||
}
|
||||
|
||||
private function formatFlags() : string
|
||||
|
||||
@@ -138,7 +138,7 @@ class LootByContainer extends Loot
|
||||
$groupChances[$k] = (100 - $sum) / ($nGroupEquals[$k] ?: 1);
|
||||
}
|
||||
|
||||
if ($cnd->getBySourceGroup($lootId, Conditions::lootTableToConditionSource($tableName))->prepare())
|
||||
if ($cnd->getBySource(Conditions::lootTableToConditionSource($tableName), group: $lootId)->prepare())
|
||||
{
|
||||
$this->storeJSGlobals($cnd->getJsGlobals());
|
||||
$cnd->toListviewColumn($loot, $this->extraCols, $lootId, 'content');
|
||||
|
||||
@@ -171,7 +171,7 @@ class LootByItem extends Loot
|
||||
if ($newRefs)
|
||||
{
|
||||
$cnd = new Conditions();
|
||||
if ($cnd->getBySourceEntry($this->entry, Conditions::SRC_REFERENCE_LOOT_TEMPLATE))
|
||||
if ($cnd->getBySource(Conditions::SRC_REFERENCE_LOOT_TEMPLATE, entry: $this->entry))
|
||||
if ($cnd->toListviewColumn($newRefs, $x, $this->entry))
|
||||
$this->storejsGlobals($cnd->getJsGlobals());
|
||||
}
|
||||
|
||||
1
setup/sql/updates/1763677664_01.sql
Normal file
1
setup/sql/updates/1763677664_01.sql
Normal file
@@ -0,0 +1 @@
|
||||
UPDATE `aowow_dbversion` SET `build` = CONCAT(IFNULL(`build`, ''), ' globaljs');
|
||||
@@ -465,6 +465,18 @@ var Markup = {
|
||||
return [str, '</span>'];
|
||||
}
|
||||
},
|
||||
condition:
|
||||
{
|
||||
ltrim: true,
|
||||
rtrim: true,
|
||||
empty: false,
|
||||
allowedClass: MARKUP_CLASS_STAFF,
|
||||
allowedChildren: { '<text>': 1 },
|
||||
toHtml: function(attr)
|
||||
{
|
||||
return ['<span>' + Markup.toHtml(ConditionList.createCell(JSON.parse(attr._nodes[0].attr._rawText)), { skipReset: true }) + '</span>'];
|
||||
}
|
||||
},
|
||||
copy:
|
||||
{
|
||||
empty: false,
|
||||
|
||||
Reference in New Issue
Block a user