enleve les fichier en trop

This commit is contained in:
compil 2017-10-20 21:43:50 +02:00
parent 33f3f13dac
commit 675bcee591
24 changed files with 0 additions and 48790 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,564 +0,0 @@
-- In this file we define functions that serves outgame character creation
------------------------------------------------------------------------------------------------------------
-- create the game namespace without reseting if already created in an other file.
<<<<<<< HEAD
if (outgame==nil) then
outgame= {};
end
------------------------------------------------------------------------------------------------------------
-- Name generator.
function outgame:procGenerateName()
local uiNameFull = getUI("ui:outgame:appear_name:name_full");
local uiNameDef = getUI("ui:outgame:appear_name:name_def");
local uiGenText = getUI("ui:outgame:appear_name:eb");
local dbNameSyllabe = getDbProp("UI:TEMP:NAME_SYLLABE");
local dbNameRace = getDbProp("UI:TEMP:NAME_RACE");
local dbNameSyllabeMax = getDbProp("UI:TEMP:NAME_SYLLABE_MAX");
local nameResult = "";
local fullnameResult = "";
local defResult = "";
local nbRafsi = 0;
for _ in pairs(rafsi) do nbRafsi = nbRafsi + 1 end
index = math.random(nbRafsi);
nameResult = rafsi[index];
fullnameResult = gismu[index];
defResult = def[index];
imax = tonumber(dbNameSyllabe);
for i=2,imax,1 do
index = math.random(nbRafsi);
nameResult = nameResult .. rafsi[index];
fullnameResult = fullnameResult .. " " .. gismu[index];
defResult = defResult .. " | " .. def[index];
end
uiNameFull.hardtext = fullnameResult;
uiNameDef.hardtext = defResult;
nameResult = string.gsub(nameResult, "'", "");
nameResult = string.gsub(nameResult, " ", "");
nameResult = string.gsub(nameResult, "-", "");
nameResult = string.lower( nameResult );
nameResult = nameResult:gsub("^%l", string.upper);
uiGenText.input_string = nameResult;
end
-- Name syllabe slider update.
function outgame:procUpdateNameSyllabeLabel()
local uiNameSyllabeText_nb = getUI("ui:outgame:appear_name:name_syllabe_slider:name_syllabe_nb");
local uiNameSyllabe = getDbProp("UI:TEMP:NAME_SYLLABE");
uiNameSyllabeText_nb.hardtext = uiNameSyllabe;
-- uiNameSyllabeText.hardtext = uiNameSyllabe .. " " .. i18n.get("uiCP_Syllabe");
=======
if (outgame == nil) then
outgame = {}
end
------------------------------------------------------------------------------------------------------------
-- Name generator.
--nb noms:
-- matis: male 621 - female 621 - FirstName 621
-- fyros: given name 14269, FirstName 841
-- zorai: given name one 318, given name two 644, FirstName 1287
-- tryker: given name 4500, FirstName 4335
-- Fyros
function outgame:getFyrosFirstName()
local nbFyrosFirstNames = #fyrosFirstNames
return fyrosFirstNames[math.random(nbFyrosFirstNames)]
end
function outgame:getFyrosLastName()
local nbFyrosLastNames = #fyrosLastNames
return fyrosLastNames[math.random(nbFyrosLastNames)]
end
-- Matis
function outgame:getMatisFirstName(sex)
-- 1 = male, 2 = female
local dbNameSex = getDbProp("UI:TEMP:NAME_SEX")
if sex ~= nil then
dbNameSex = sex
end
local FirstName = ""
if tonumber(dbNameSex) == 1 then
local nbMatisMaleFirstNames = #matisMaleFirstNames
FirstName = matisMaleFirstNames[math.random(nbMatisMaleFirstNames)]
else
local nbMatisFemaleFirstNames = #matisFemaleFirstNames
FirstName = matisFemaleFirstNames[math.random(nbMatisFemaleFirstNames)]
end
return FirstName
end
function outgame:getMatisLastName()
local nbMatisLastNames = #matisLastNames
return matisLastNames[math.random(nbMatisLastNames)]
end
-- Tryker
function outgame:getTrykerFirstName()
local nbTrykerFirstNames = #trykerFirstNames
return trykerFirstNames[math.random(nbTrykerFirstNames)]
end
function outgame:getTrykerLastName()
local nbTrykerLastNames = #trykerLastNames
return trykerLastNames[math.random(nbTrykerLastNames)]
end
-- Zoraï
function outgame:getZoraiFirstName()
local nbFirstNamesOne = #zoraiFirstNamesOne
local FirstNameOne = zoraiFirstNamesOne[math.random(nbFirstNamesOne)]
local nbFirstNamesTwo = #zoraiFirstNamesTwo
local FirstNameTwo = zoraiFirstNamesTwo[math.random(nbFirstNamesTwo)]
return FirstNameOne .. "-" .. FirstNameTwo
end
function outgame:getZoraiLastName()
local nbLastNames = #zoraiLastNames
return zoraiLastNames[math.random(nbLastNames)]
end
function outgame:procGenerateName()
local uiNameFull = getUI("ui:outgame:appear_name:name_full")
local uiGenText = getUI("ui:outgame:appear_name:eb")
local dbNameRace = getDbProp("UI:TEMP:NAME_RACE")
local dbNameSubRaceFirstName = getDbProp("UI:TEMP:NAME_SUB_RACE_FIRST_NAME")
local dbNameSubRaceLastName = getDbProp("UI:TEMP:NAME_SUB_RACE_LAST_NAME")
local nameResult = ""
local fullnameResult = ""
-- Look at outgame:procUpdateNameRaceLabel() for the "race" list.
-- fy ma try zo -->
local firstName = "test2"
local lastName = "test"
-- Fyros and Matis are using "first name, last name" order
-- Trykers and Zoraïs are using "last name, first name" order
if tonumber(dbNameRace) == 1 then
-- Fyros
firstName = self:getFyrosFirstName()
lastName = self:getFyrosLastName()
fullnameResult = firstName .. " " .. lastName
elseif tonumber(dbNameRace) == 2 then
-- Matis
firstName = self:getMatisFirstName()
lastName = self:getMatisLastName()
fullnameResult = firstName .. " " .. lastName
elseif tonumber(dbNameRace) == 3 then
-- Tryker
firstName = self:getTrykerFirstName()
lastName = self:getTrykerLastName()
fullnameResult = lastName .. " " .. firstName
elseif tonumber(dbNameRace) == 4 then
-- Zorai
firstName = self:getZoraiFirstName()
lastName = self:getZoraiLastName()
fullnameResult = lastName .. " " .. firstName
elseif tonumber(dbNameRace) == 5 then
-- Maraudeurs
-- firstName
if tonumber(dbNameSubRaceFirstName) == 1 then
-- Fyros
firstName = self:getFyrosFirstName()
elseif tonumber(dbNameSubRaceFirstName) == 2 then
-- Matis M
firstName = self:getMatisFirstName(1)
elseif tonumber(dbNameSubRaceFirstName) == 3 then
-- Matis F
firstName = self:getMatisFirstName(2)
elseif tonumber(dbNameSubRaceFirstName) == 4 then
-- Tryker
firstName = self:getTrykerFirstName()
elseif tonumber(dbNameSubRaceFirstName) == 5 then
-- Zorai
firstName = self:getZoraiFirstName()
end
-- lastName
if tonumber(dbNameSubRaceLastName) == 1 then
-- Fyros
lastName = self:getFyrosLastName()
elseif tonumber(dbNameSubRaceLastName) == 2 then
-- Matis
lastName = self:getMatisLastName()
elseif tonumber(dbNameSubRaceLastName) == 3 then
-- Tryker
lastName = self:getTrykerLastName()
elseif tonumber(dbNameSubRaceLastName) == 4 then
-- Zorai
lastName = self:getZoraiLastName()
end
fullnameResult = firstName .. " " .. lastName
end
-- always use first name for character name
nameResult = firstName
uiNameFull.hardtext = fullnameResult
nameResult = string.gsub(nameResult, "'", "")
nameResult = string.gsub(nameResult, " ", "")
nameResult = string.gsub(nameResult, "-", "")
nameResult = string.lower(nameResult)
nameResult = nameResult:gsub("^%l", string.upper)
uiGenText.input_string = nameResult
end
-- Name sex slider update.
function outgame:procUpdateNameSexLabel()
local nameSexType = { "uiCP_Sex_Male", "uiCP_Sex_Female" }
local uiNameSexText = getUI("ui:outgame:appear_name:name_sex_slider:name_sex")
local uiNameSex = getDbProp("UI:TEMP:NAME_SEX")
tempstr = tostring(i18n.get(nameSexType[tonumber(uiNameSex)]))
tempstr = string.lower(tempstr)
tempstr = (tempstr:gsub("^%l", string.upper))
uiNameSexText.hardtext = tempstr
end
-- Name race slider update.
function outgame:procUpdateNameRaceLabel()
local nameRaceType = { "Fyros", "Matis", "Tryker", "Zoraï", "uiCP_Maraudeur" }
local uiNameRaceText = getUI("ui:outgame:appear_name:name_race_slider:name_race")
local dbNameRace = getDbProp("UI:TEMP:NAME_RACE")
local uiNameSexSlider = getUI("ui:outgame:appear_name:name_sex_slider")
local uiNameSubRaceFirstNameSlider = getUI("ui:outgame:appear_name:name_sub_race_first_name_slider")
local uiNameSubRaceLastNameSlider = getUI("ui:outgame:appear_name:name_sub_race_last_name_slider")
local uiNameGenerate = getUI("ui:outgame:appear_name:generate")
-- Show/Hide sex slider
uiNameGenerate.y = "-50"
if tonumber(dbNameRace) == 2 then
uiNameSexSlider.active = true
uiNameGenerate.y = "-65"
else
uiNameSexSlider.active = false
end
-- Show/Hide sub race slider
if tonumber(dbNameRace) == 5 then
uiNameSubRaceFirstNameSlider.active = true
uiNameSubRaceLastNameSlider.active = true
uiNameGenerate.y = "-105"
else
uiNameSubRaceFirstNameSlider.active = false
uiNameSubRaceLastNameSlider.active = false
end
uiNameRaceText.hardtext = tostring(nameRaceType[tonumber(dbNameRace)])
end
local matisF = "Matis " .. (string.lower(tostring(i18n.get("uiCP_Sex_Female")) )):gsub("^%l", string.upper)
local matisM = "Matis " .. (string.lower(tostring(i18n.get("uiCP_Sex_Male")) )):gsub("^%l", string.upper)
function outgame:procUpdateNameSubRaceFirstNameLabel()
local nameSubRaceFirstNameType = { "Fyros", matisM, matisF, "Tryker", "Zoraï" }
local uiNameSubRaceFirstNameText = getUI("ui:outgame:appear_name:name_sub_race_first_name_slider:name_race")
local dbNameSubRaceFirstName = getDbProp("UI:TEMP:NAME_SUB_RACE_FIRST_NAME")
uiNameSubRaceFirstNameText.hardtext= tostring(nameSubRaceFirstNameType[tonumber(dbNameSubRaceFirstName)])
end
function outgame:procUpdateNameSubRaceLastNameLabel()
local nameSubRaceLastNameType = { "Fyros", "Matis", "Tryker", "Zoraï" }
local uiNameSubRaceLastNameText = getUI("ui:outgame:appear_name:name_sub_race_last_name_slider:name_race")
local dbNameSubRaceLastName = getDbProp("UI:TEMP:NAME_SUB_RACE_LAST_NAME")
uiNameSubRaceLastNameText.hardtext= tostring(nameSubRaceLastNameType[tonumber(dbNameSubRaceLastName)])
>>>>>>> ryzomcore
end
------------------------------------------------------------------------------------------------------------
-- called to construct icons
function outgame:activePackElement(id, icon)
<<<<<<< HEAD
local uiDesc = getUI("ui:outgame:appear:job_options:options:desc");
uiDesc['ico' .. tostring(id)].active= true;
uiDesc['ico' .. tostring(id)].texture= icon;
uiDesc['ico' .. tostring(id) .. 'txt'].active= true;
=======
local uiDesc = getUI("ui:outgame:appear:job_options:options:desc")
uiDesc['ico' .. tostring(id)].active = true
uiDesc['ico' .. tostring(id)].texture = icon
uiDesc['ico' .. tostring(id) .. 'txt'].active = true
>>>>>>> ryzomcore
end
------------------------------------------------------------------------------------------------------------
-- called to construct pack text
function outgame:setPackJobText(id, spec)
-- Set Pack content
<<<<<<< HEAD
local uiPackText = getUI("ui:outgame:appear:job_options:options:desc:pack_" .. id);
uiPackText.hardtext= "uiCP_Job_" .. id .. tostring(spec);
-- Set specialization text
local uiResText = getUI("ui:outgame:appear:job_options:options:result:res");
if(spec==2) then
uiResText.hardtext= "uiCP_Res_" .. id;
=======
local uiPackText = getUI("ui:outgame:appear:job_options:options:desc:pack_" .. id)
uiPackText.hardtext= "uiCP_Job_" .. id .. tostring(spec)
-- Set specialization text
local uiResText = getUI("ui:outgame:appear:job_options:options:result:res")
if(spec==2) then
uiResText.hardtext= "uiCP_Res_" .. id
>>>>>>> ryzomcore
end
end
------------------------------------------------------------------------------------------------------------
-- called to construct pack
function outgame:buildActionPack()
<<<<<<< HEAD
local uiDesc = getUI("ui:outgame:appear:job_options:options:desc");
if (uiDesc==nil) then
return;
=======
local uiDesc = getUI("ui:outgame:appear:job_options:options:desc")
if (uiDesc==nil) then
return
>>>>>>> ryzomcore
end
-- Reset All
for i = 1,20 do
<<<<<<< HEAD
uiDesc['ico' .. tostring(i)].active= false;
uiDesc['ico' .. tostring(i) .. 'txt'].active= false;
end
-- Build Default Combat
self:activePackElement(1, 'f1.tga'); -- Dagger
self:activePackElement(2, 'f2.tga'); -- Accurate Attack
-- Build Default Magic
self:activePackElement(6, 'm2.tga'); -- Gloves
self:activePackElement(7, 'm1.tga'); -- Acid
-- Build Default Forage
self:activePackElement(11, 'g1.tga'); -- Forage Tool
self:activePackElement(12, 'g2.tga'); -- Basic Extract
-- Build Default Craft
self:activePackElement(16, 'c2.tga'); -- Craft Tool
self:activePackElement(17, 'c1.tga'); -- 50 raw mat
self:activePackElement(18, 'c3.tga'); -- Craft Root
self:activePackElement(19, 'c4.tga'); -- Boots Plan
-- Build Option
if (getDbProp('UI:TEMP:JOB_FIGHT') == 2) then
self:activePackElement(3, 'f3.tga'); -- Increase damage
elseif (getDbProp('UI:TEMP:JOB_MAGIC') == 2) then
self:activePackElement(8, 'm5.tga'); -- Fear
elseif (getDbProp('UI:TEMP:JOB_FORAGE') == 2) then
self:activePackElement(13, 'g3.tga'); -- Basic Prospection
elseif (getDbProp('UI:TEMP:JOB_CRAFT') == 2) then
self:activePackElement(20, 'c6.tga'); -- Gloves Plan
self:activePackElement(17, 'c5.tga'); -- Replace 17, with 100x RawMat
=======
uiDesc['ico' .. tostring(i)].active = false
uiDesc['ico' .. tostring(i) .. 'txt'].active = false
end
-- Build Default Combat
self:activePackElement(1, 'f1.tga') -- Dagger
self:activePackElement(2, 'f2.tga') -- Accurate Attack
-- Build Default Magic
self:activePackElement(6, 'm2.tga') -- Gloves
self:activePackElement(7, 'm1.tga') -- Acid
-- Build Default Forage
self:activePackElement(11, 'g1.tga') -- Forage Tool
self:activePackElement(12, 'g2.tga') -- Basic Extract
-- Build Default Craft
self:activePackElement(16, 'c2.tga') -- Craft Tool
self:activePackElement(17, 'c1.tga') -- 50 raw mat
self:activePackElement(18, 'c3.tga') -- Craft Root
self:activePackElement(19, 'c4.tga') -- Boots Plan
-- Build Option
if (getDbProp('UI:TEMP:JOB_FIGHT') == 2) then
self:activePackElement(3, 'f3.tga') -- Increase damage
elseif (getDbProp('UI:TEMP:JOB_MAGIC') == 2) then
self:activePackElement(8, 'm5.tga') -- Fear
elseif (getDbProp('UI:TEMP:JOB_FORAGE') == 2) then
self:activePackElement(13, 'g3.tga') -- Basic Prospection
elseif (getDbProp('UI:TEMP:JOB_CRAFT') == 2) then
self:activePackElement(20, 'c6.tga') -- Gloves Plan
self:activePackElement(17, 'c5.tga') -- Replace 17, with 100x RawMat
>>>>>>> ryzomcore
end
-- Reset Text
<<<<<<< HEAD
self:setPackJobText('F', 1);
self:setPackJobText('M', 1);
self:setPackJobText('G', 1);
self:setPackJobText('C', 1);
-- Set correct text for specalized version
if (getDbProp('UI:TEMP:JOB_FIGHT') == 2) then
self:setPackJobText('F', 2);
elseif (getDbProp('UI:TEMP:JOB_MAGIC') == 2) then
self:setPackJobText('M', 2);
elseif (getDbProp('UI:TEMP:JOB_FORAGE') == 2) then
self:setPackJobText('G', 2);
elseif (getDbProp('UI:TEMP:JOB_CRAFT') == 2) then
self:setPackJobText('C', 2);
end
=======
self:setPackJobText('F', 1)
self:setPackJobText('M', 1)
self:setPackJobText('G', 1)
self:setPackJobText('C', 1)
-- Set correct text for specalized version
if (getDbProp('UI:TEMP:JOB_FIGHT') == 2) then
self:setPackJobText('F', 2)
elseif (getDbProp('UI:TEMP:JOB_MAGIC') == 2) then
self:setPackJobText('M', 2)
elseif (getDbProp('UI:TEMP:JOB_FORAGE') == 2) then
self:setPackJobText('G', 2)
elseif (getDbProp('UI:TEMP:JOB_CRAFT') == 2) then
self:setPackJobText('C', 2)
end
>>>>>>> ryzomcore
end
------------------------------------------------------------------------------------------------------------
-------------------
-- BG DOWNLOADER --
-------------------
--function outgame:getProgressGroup()
-- --debugInfo("*** 1 ***")
-- local grp = getUI("ui:outgame:charsel:bgd_progress")
-- --debugInfo(tostring(grp))
-- return grp
--end
--
--function outgame:setProgressText(ucstr, color, progress, ellipsis)
-- --debugInfo("*** 2 ***")
-- local text = self:getProgressGroup():find("text")
-- local ellipsisTxt = self:getProgressGroup():find("ellipsis")
-- text.color = color
-- text.uc_hardtext = ucstr
-- if ellipsis then
-- ellipsisTxt.hardtext = ellipsis
-- else
-- ellipsisTxt.hardtext = ""
-- end
-- ellipsisTxt.color = color
-- local progressCtrl = self:getProgressGroup():find("progress")
-- progressCtrl.range = 100
-- progressCtrl.value = progress * 100
-- progressCtrl.active = true
--end
--
--
--local progress progressSymbol = { ".", "..", "..." }
--
---- set patching progression (from 0 to 1)
--function outgame:setPatchProgress(progress)
-- --debugInfo("*** 3 ***")
-- local progressPercentText = string.format("%d%%", 100 * progress)
<<<<<<< HEAD
-- local progressPostfix = math.fmod(os.time(), 3)
-- --debugInfo("Patch in progress : " .. tostring(progress))
=======
-- local progressPostfix = math.fmod(os.time(), 3)
-- --debugInfo("Patch in progress : " .. tostring(progress))
>>>>>>> ryzomcore
-- local progressDate = nltime.getLocalTime() / 500
-- local colValue = math.floor(230 + 24 * math.sin(progressDate))
-- local color = string.format("%d %d %d %d", colValue, colValue, colValue, 255)
-- self:setProgressText(concatUCString(i18n.get("uiBGD_Progress"), ucstring(progressPercentText)), color, progress, progressSymbol[progressPostfix + 1])
--end
--
--function outgame:setPatchSuccess()
-- --debugInfo("*** 4 ***")
-- --debugInfo("Patch up to date")
-- self:setProgressText(i18n.get("uiBGD_PatchUpToDate"), "0 255 0 255", 1)
--end
--
--
--function outgame:setPatchError()
-- --debugInfo("*** 5 ***")
<<<<<<< HEAD
-- --debugInfo("Patch error")
=======
-- --debugInfo("Patch error")
>>>>>>> ryzomcore
-- self:setProgressText(i18n.get("uiBGD_PatchError"), "255 0 0 255", 0)
--end
--
--function outgame:setNoPatch()
-- --self:getProgressGroup().active = false
--end
------------------------------------------------------------------------------------------------------------
----------------
--LAUNCH GAME --
----------------
function outgame:launchGame()
if not isPlayerSlotNewbieLand(getPlayerSelectedSlot()) then
if not isFullyPatched() then
<<<<<<< HEAD
messageBoxWithHelp(i18n.get("uiBGD_MainlandCharFullPatchNeeded"), "ui:outgame")
return
end
end
=======
messageBoxWithHelp(i18n.get("uiBGD_MainlandCharFullPatchNeeded"), "ui:outgame")
return
end
end
>>>>>>> ryzomcore
runAH(getUICaller(), "proc", "proc_charsel_play")
end

View file

@ -1,227 +0,0 @@
-- In this file we define functions that serves outgame character creation
------------------------------------------------------------------------------------------------------------
-- create the game namespace without reseting if already created in an other file.
if (outgame==nil) then
outgame= {};
end
------------------------------------------------------------------------------------------------------------
-- Name generator.
function outgame:procGenerateName()
local uiNameFull = getUI("ui:outgame:appear_name:name_full");
local uiNameDef = getUI("ui:outgame:appear_name:name_def");
local uiGenText = getUI("ui:outgame:appear_name:eb");
local dbNameSyllabe = getDbProp("UI:TEMP:NAME_SYLLABE");
local dbNameRace = getDbProp("UI:TEMP:NAME_RACE");
local dbNameSyllabeMax = getDbProp("UI:TEMP:NAME_SYLLABE_MAX");
local nameResult = "";
local fullnameResult = "";
local defResult = "";
local nbRafsi = 0;
for _ in pairs(rafsi) do nbRafsi = nbRafsi + 1 end
index = math.random(nbRafsi);
nameResult = rafsi[index];
fullnameResult = gismu[index];
defResult = def[index];
imax = tonumber(dbNameSyllabe);
for i=2,imax,1 do
index = math.random(nbRafsi);
nameResult = nameResult .. rafsi[index];
fullnameResult = fullnameResult .. " " .. gismu[index];
defResult = defResult .. " | " .. def[index];
end
uiNameFull.hardtext = fullnameResult;
uiNameDef.hardtext = defResult;
nameResult = string.gsub(nameResult, "'", "");
nameResult = string.gsub(nameResult, " ", "");
nameResult = string.gsub(nameResult, "-", "");
nameResult = string.lower( nameResult );
nameResult = nameResult:gsub("^%l", string.upper);
uiGenText.input_string = nameResult;
end
-- Name syllabe slider update.
function outgame:procUpdateNameSyllabeLabel()
local uiNameSyllabeText_nb = getUI("ui:outgame:appear_name:name_syllabe_slider:name_syllabe_nb");
local uiNameSyllabe = getDbProp("UI:TEMP:NAME_SYLLABE");
uiNameSyllabeText_nb.hardtext = uiNameSyllabe;
-- uiNameSyllabeText.hardtext = uiNameSyllabe .. " " .. i18n.get("uiCP_Syllabe");
end
------------------------------------------------------------------------------------------------------------
-- called to construct icons
function outgame:activePackElement(id, icon)
local uiDesc = getUI("ui:outgame:appear:job_options:options:desc");
uiDesc['ico' .. tostring(id)].active= true;
uiDesc['ico' .. tostring(id)].texture= icon;
uiDesc['ico' .. tostring(id) .. 'txt'].active= true;
end
------------------------------------------------------------------------------------------------------------
-- called to construct pack text
function outgame:setPackJobText(id, spec)
-- Set Pack content
local uiPackText = getUI("ui:outgame:appear:job_options:options:desc:pack_" .. id);
uiPackText.hardtext= "uiCP_Job_" .. id .. tostring(spec);
-- Set specialization text
local uiResText = getUI("ui:outgame:appear:job_options:options:result:res");
if(spec==2) then
uiResText.hardtext= "uiCP_Res_" .. id;
end
end
------------------------------------------------------------------------------------------------------------
-- called to construct pack
function outgame:buildActionPack()
local uiDesc = getUI("ui:outgame:appear:job_options:options:desc");
if (uiDesc==nil) then
return;
end
-- Reset All
for i = 1,20 do
uiDesc['ico' .. tostring(i)].active= false;
uiDesc['ico' .. tostring(i) .. 'txt'].active= false;
end
-- Build Default Combat
self:activePackElement(1, 'f1.tga'); -- Dagger
self:activePackElement(2, 'f2.tga'); -- Accurate Attack
-- Build Default Magic
self:activePackElement(6, 'm2.tga'); -- Gloves
self:activePackElement(7, 'm1.tga'); -- Acid
-- Build Default Forage
self:activePackElement(11, 'g1.tga'); -- Forage Tool
self:activePackElement(12, 'g2.tga'); -- Basic Extract
-- Build Default Craft
self:activePackElement(16, 'c2.tga'); -- Craft Tool
self:activePackElement(17, 'c1.tga'); -- 50 raw mat
self:activePackElement(18, 'c3.tga'); -- Craft Root
self:activePackElement(19, 'c4.tga'); -- Boots Plan
-- Build Option
if (getDbProp('UI:TEMP:JOB_FIGHT') == 2) then
self:activePackElement(3, 'f3.tga'); -- Increase damage
elseif (getDbProp('UI:TEMP:JOB_MAGIC') == 2) then
self:activePackElement(8, 'm5.tga'); -- Fear
elseif (getDbProp('UI:TEMP:JOB_FORAGE') == 2) then
self:activePackElement(13, 'g3.tga'); -- Basic Prospection
elseif (getDbProp('UI:TEMP:JOB_CRAFT') == 2) then
self:activePackElement(20, 'c6.tga'); -- Gloves Plan
self:activePackElement(17, 'c5.tga'); -- Replace 17, with 100x RawMat
end
-- Reset Text
self:setPackJobText('F', 1);
self:setPackJobText('M', 1);
self:setPackJobText('G', 1);
self:setPackJobText('C', 1);
-- Set correct text for specalized version
if (getDbProp('UI:TEMP:JOB_FIGHT') == 2) then
self:setPackJobText('F', 2);
elseif (getDbProp('UI:TEMP:JOB_MAGIC') == 2) then
self:setPackJobText('M', 2);
elseif (getDbProp('UI:TEMP:JOB_FORAGE') == 2) then
self:setPackJobText('G', 2);
elseif (getDbProp('UI:TEMP:JOB_CRAFT') == 2) then
self:setPackJobText('C', 2);
end
end
------------------------------------------------------------------------------------------------------------
-------------------
-- BG DOWNLOADER --
-------------------
--function outgame:getProgressGroup()
-- --debugInfo("*** 1 ***")
-- local grp = getUI("ui:outgame:charsel:bgd_progress")
-- --debugInfo(tostring(grp))
-- return grp
--end
--
--function outgame:setProgressText(ucstr, color, progress, ellipsis)
-- --debugInfo("*** 2 ***")
-- local text = self:getProgressGroup():find("text")
-- local ellipsisTxt = self:getProgressGroup():find("ellipsis")
-- text.color = color
-- text.uc_hardtext = ucstr
-- if ellipsis then
-- ellipsisTxt.hardtext = ellipsis
-- else
-- ellipsisTxt.hardtext = ""
-- end
-- ellipsisTxt.color = color
-- local progressCtrl = self:getProgressGroup():find("progress")
-- progressCtrl.range = 100
-- progressCtrl.value = progress * 100
-- progressCtrl.active = true
--end
--
--
--local progress progressSymbol = { ".", "..", "..." }
--
---- set patching progression (from 0 to 1)
--function outgame:setPatchProgress(progress)
-- --debugInfo("*** 3 ***")
-- local progressPercentText = string.format("%d%%", 100 * progress)
-- local progressPostfix = math.fmod(os.time(), 3)
-- --debugInfo("Patch in progress : " .. tostring(progress))
-- local progressDate = nltime.getLocalTime() / 500
-- local colValue = math.floor(230 + 24 * math.sin(progressDate))
-- local color = string.format("%d %d %d %d", colValue, colValue, colValue, 255)
-- self:setProgressText(concatUCString(i18n.get("uiBGD_Progress"), ucstring(progressPercentText)), color, progress, progressSymbol[progressPostfix + 1])
--end
--
--function outgame:setPatchSuccess()
-- --debugInfo("*** 4 ***")
-- --debugInfo("Patch up to date")
-- self:setProgressText(i18n.get("uiBGD_PatchUpToDate"), "0 255 0 255", 1)
--end
--
--
--function outgame:setPatchError()
-- --debugInfo("*** 5 ***")
-- --debugInfo("Patch error")
-- self:setProgressText(i18n.get("uiBGD_PatchError"), "255 0 0 255", 0)
--end
--
--function outgame:setNoPatch()
-- --self:getProgressGroup().active = false
--end
------------------------------------------------------------------------------------------------------------
----------------
--LAUNCH GAME --
----------------
function outgame:launchGame()
if not isPlayerSlotNewbieLand(getPlayerSelectedSlot()) then
if not isFullyPatched() then
messageBoxWithHelp(i18n.get("uiBGD_MainlandCharFullPatchNeeded"), "ui:outgame")
return
end
end
runAH(getUICaller(), "proc", "proc_charsel_play")
end

View file

@ -1,414 +0,0 @@
-- In this file we define functions that serves outgame character creation
------------------------------------------------------------------------------------------------------------
-- create the game namespace without reseting if already created in an other file.
if (outgame == nil) then
outgame = {}
end
------------------------------------------------------------------------------------------------------------
-- Name generator.
--nb noms:
-- matis: male 621 - female 621 - FirstName 621
-- fyros: given name 14269, FirstName 841
-- zorai: given name one 318, given name two 644, FirstName 1287
-- tryker: given name 4500, FirstName 4335
-- Fyros
function outgame:getFyrosFirstName()
local nbFyrosFirstNames = #fyrosFirstNames
return fyrosFirstNames[math.random(nbFyrosFirstNames)]
end
function outgame:getFyrosLastName()
local nbFyrosLastNames = #fyrosLastNames
return fyrosLastNames[math.random(nbFyrosLastNames)]
end
-- Matis
function outgame:getMatisFirstName(sex)
-- 1 = male, 2 = female
local dbNameSex = getDbProp("UI:TEMP:NAME_SEX")
if sex ~= nil then
dbNameSex = sex
end
local FirstName = ""
if tonumber(dbNameSex) == 1 then
local nbMatisMaleFirstNames = #matisMaleFirstNames
FirstName = matisMaleFirstNames[math.random(nbMatisMaleFirstNames)]
else
local nbMatisFemaleFirstNames = #matisFemaleFirstNames
FirstName = matisFemaleFirstNames[math.random(nbMatisFemaleFirstNames)]
end
return FirstName
end
function outgame:getMatisLastName()
local nbMatisLastNames = #matisLastNames
return matisLastNames[math.random(nbMatisLastNames)]
end
-- Tryker
function outgame:getTrykerFirstName()
local nbTrykerFirstNames = #trykerFirstNames
return trykerFirstNames[math.random(nbTrykerFirstNames)]
end
function outgame:getTrykerLastName()
local nbTrykerLastNames = #trykerLastNames
return trykerLastNames[math.random(nbTrykerLastNames)]
end
-- Zoraï
function outgame:getZoraiFirstName()
local nbFirstNamesOne = #zoraiFirstNamesOne
local FirstNameOne = zoraiFirstNamesOne[math.random(nbFirstNamesOne)]
local nbFirstNamesTwo = #zoraiFirstNamesTwo
local FirstNameTwo = zoraiFirstNamesTwo[math.random(nbFirstNamesTwo)]
return FirstNameOne .. "-" .. FirstNameTwo
end
function outgame:getZoraiLastName()
local nbLastNames = #zoraiLastNames
return zoraiLastNames[math.random(nbLastNames)]
end
function outgame:procGenerateName()
local uiNameFull = getUI("ui:outgame:appear_name:name_full")
local uiGenText = getUI("ui:outgame:appear_name:eb")
local dbNameRace = getDbProp("UI:TEMP:NAME_RACE")
local dbNameSubRaceFirstName = getDbProp("UI:TEMP:NAME_SUB_RACE_FIRST_NAME")
local dbNameSubRaceLastName = getDbProp("UI:TEMP:NAME_SUB_RACE_LAST_NAME")
local nameResult = ""
local fullnameResult = ""
-- Look at outgame:procUpdateNameRaceLabel() for the "race" list.
-- fy ma try zo -->
local firstName = "test2"
local lastName = "test"
-- Fyros and Matis are using "first name, last name" order
-- Trykers and Zoraïs are using "last name, first name" order
if tonumber(dbNameRace) == 1 then
-- Fyros
firstName = self:getFyrosFirstName()
lastName = self:getFyrosLastName()
fullnameResult = firstName .. " " .. lastName
elseif tonumber(dbNameRace) == 2 then
-- Matis
firstName = self:getMatisFirstName()
lastName = self:getMatisLastName()
fullnameResult = firstName .. " " .. lastName
elseif tonumber(dbNameRace) == 3 then
-- Tryker
firstName = self:getTrykerFirstName()
lastName = self:getTrykerLastName()
fullnameResult = lastName .. " " .. firstName
elseif tonumber(dbNameRace) == 4 then
-- Zorai
firstName = self:getZoraiFirstName()
lastName = self:getZoraiLastName()
fullnameResult = lastName .. " " .. firstName
elseif tonumber(dbNameRace) == 5 then
-- Maraudeurs
-- firstName
if tonumber(dbNameSubRaceFirstName) == 1 then
-- Fyros
firstName = self:getFyrosFirstName()
elseif tonumber(dbNameSubRaceFirstName) == 2 then
-- Matis M
firstName = self:getMatisFirstName(1)
elseif tonumber(dbNameSubRaceFirstName) == 3 then
-- Matis F
firstName = self:getMatisFirstName(2)
elseif tonumber(dbNameSubRaceFirstName) == 4 then
-- Tryker
firstName = self:getTrykerFirstName()
elseif tonumber(dbNameSubRaceFirstName) == 5 then
-- Zorai
firstName = self:getZoraiFirstName()
end
-- lastName
if tonumber(dbNameSubRaceLastName) == 1 then
-- Fyros
lastName = self:getFyrosLastName()
elseif tonumber(dbNameSubRaceLastName) == 2 then
-- Matis
lastName = self:getMatisLastName()
elseif tonumber(dbNameSubRaceLastName) == 3 then
-- Tryker
lastName = self:getTrykerLastName()
elseif tonumber(dbNameSubRaceLastName) == 4 then
-- Zorai
lastName = self:getZoraiLastName()
end
fullnameResult = firstName .. " " .. lastName
end
-- always use first name for character name
nameResult = firstName
uiNameFull.hardtext = fullnameResult
nameResult = string.gsub(nameResult, "'", "")
nameResult = string.gsub(nameResult, " ", "")
nameResult = string.gsub(nameResult, "-", "")
nameResult = string.lower(nameResult)
nameResult = nameResult:gsub("^%l", string.upper)
uiGenText.input_string = nameResult
end
-- Name sex slider update.
function outgame:procUpdateNameSexLabel()
local nameSexType = { "uiCP_Sex_Male", "uiCP_Sex_Female" }
local uiNameSexText = getUI("ui:outgame:appear_name:name_sex_slider:name_sex")
local uiNameSex = getDbProp("UI:TEMP:NAME_SEX")
tempstr = tostring(i18n.get(nameSexType[tonumber(uiNameSex)]))
tempstr = string.lower(tempstr)
tempstr = (tempstr:gsub("^%l", string.upper))
uiNameSexText.hardtext = tempstr
end
-- Name race slider update.
function outgame:procUpdateNameRaceLabel()
local nameRaceType = { "Fyros", "Matis", "Tryker", "Zoraï", "uiCP_Maraudeur" }
local uiNameRaceText = getUI("ui:outgame:appear_name:name_race_slider:name_race")
local dbNameRace = getDbProp("UI:TEMP:NAME_RACE")
local uiNameSexSlider = getUI("ui:outgame:appear_name:name_sex_slider")
local uiNameSubRaceFirstNameSlider = getUI("ui:outgame:appear_name:name_sub_race_first_name_slider")
local uiNameSubRaceLastNameSlider = getUI("ui:outgame:appear_name:name_sub_race_last_name_slider")
local uiNameGenerate = getUI("ui:outgame:appear_name:generate")
-- Show/Hide sex slider
uiNameGenerate.y = "-50"
if tonumber(dbNameRace) == 2 then
uiNameSexSlider.active = true
uiNameGenerate.y = "-65"
else
uiNameSexSlider.active = false
end
-- Show/Hide sub race slider
if tonumber(dbNameRace) == 5 then
uiNameSubRaceFirstNameSlider.active = true
uiNameSubRaceLastNameSlider.active = true
uiNameGenerate.y = "-105"
else
uiNameSubRaceFirstNameSlider.active = false
uiNameSubRaceLastNameSlider.active = false
end
uiNameRaceText.hardtext = tostring(nameRaceType[tonumber(dbNameRace)])
end
local matisF = "Matis " .. (string.lower(tostring(i18n.get("uiCP_Sex_Female")) )):gsub("^%l", string.upper)
local matisM = "Matis " .. (string.lower(tostring(i18n.get("uiCP_Sex_Male")) )):gsub("^%l", string.upper)
function outgame:procUpdateNameSubRaceFirstNameLabel()
local nameSubRaceFirstNameType = { "Fyros", matisM, matisF, "Tryker", "Zoraï" }
local uiNameSubRaceFirstNameText = getUI("ui:outgame:appear_name:name_sub_race_first_name_slider:name_race")
local dbNameSubRaceFirstName = getDbProp("UI:TEMP:NAME_SUB_RACE_FIRST_NAME")
uiNameSubRaceFirstNameText.hardtext= tostring(nameSubRaceFirstNameType[tonumber(dbNameSubRaceFirstName)])
end
function outgame:procUpdateNameSubRaceLastNameLabel()
local nameSubRaceLastNameType = { "Fyros", "Matis", "Tryker", "Zoraï" }
local uiNameSubRaceLastNameText = getUI("ui:outgame:appear_name:name_sub_race_last_name_slider:name_race")
local dbNameSubRaceLastName = getDbProp("UI:TEMP:NAME_SUB_RACE_LAST_NAME")
uiNameSubRaceLastNameText.hardtext= tostring(nameSubRaceLastNameType[tonumber(dbNameSubRaceLastName)])
end
------------------------------------------------------------------------------------------------------------
-- called to construct icons
function outgame:activePackElement(id, icon)
local uiDesc = getUI("ui:outgame:appear:job_options:options:desc")
uiDesc['ico' .. tostring(id)].active = true
uiDesc['ico' .. tostring(id)].texture = icon
uiDesc['ico' .. tostring(id) .. 'txt'].active = true
end
------------------------------------------------------------------------------------------------------------
-- called to construct pack text
function outgame:setPackJobText(id, spec)
-- Set Pack content
local uiPackText = getUI("ui:outgame:appear:job_options:options:desc:pack_" .. id)
uiPackText.hardtext= "uiCP_Job_" .. id .. tostring(spec)
-- Set specialization text
local uiResText = getUI("ui:outgame:appear:job_options:options:result:res")
if(spec==2) then
uiResText.hardtext= "uiCP_Res_" .. id
end
end
------------------------------------------------------------------------------------------------------------
-- called to construct pack
function outgame:buildActionPack()
local uiDesc = getUI("ui:outgame:appear:job_options:options:desc")
if (uiDesc==nil) then
return
end
-- Reset All
for i = 1,20 do
uiDesc['ico' .. tostring(i)].active = false
uiDesc['ico' .. tostring(i) .. 'txt'].active = false
end
-- Build Default Combat
self:activePackElement(1, 'f1.tga') -- Dagger
self:activePackElement(2, 'f2.tga') -- Accurate Attack
-- Build Default Magic
self:activePackElement(6, 'm2.tga') -- Gloves
self:activePackElement(7, 'm1.tga') -- Acid
-- Build Default Forage
self:activePackElement(11, 'g1.tga') -- Forage Tool
self:activePackElement(12, 'g2.tga') -- Basic Extract
-- Build Default Craft
self:activePackElement(16, 'c2.tga') -- Craft Tool
self:activePackElement(17, 'c1.tga') -- 50 raw mat
self:activePackElement(18, 'c3.tga') -- Craft Root
self:activePackElement(19, 'c4.tga') -- Boots Plan
-- Build Option
if (getDbProp('UI:TEMP:JOB_FIGHT') == 2) then
self:activePackElement(3, 'f3.tga') -- Increase damage
elseif (getDbProp('UI:TEMP:JOB_MAGIC') == 2) then
self:activePackElement(8, 'm5.tga') -- Fear
elseif (getDbProp('UI:TEMP:JOB_FORAGE') == 2) then
self:activePackElement(13, 'g3.tga') -- Basic Prospection
elseif (getDbProp('UI:TEMP:JOB_CRAFT') == 2) then
self:activePackElement(20, 'c6.tga') -- Gloves Plan
self:activePackElement(17, 'c5.tga') -- Replace 17, with 100x RawMat
end
-- Reset Text
self:setPackJobText('F', 1)
self:setPackJobText('M', 1)
self:setPackJobText('G', 1)
self:setPackJobText('C', 1)
-- Set correct text for specalized version
if (getDbProp('UI:TEMP:JOB_FIGHT') == 2) then
self:setPackJobText('F', 2)
elseif (getDbProp('UI:TEMP:JOB_MAGIC') == 2) then
self:setPackJobText('M', 2)
elseif (getDbProp('UI:TEMP:JOB_FORAGE') == 2) then
self:setPackJobText('G', 2)
elseif (getDbProp('UI:TEMP:JOB_CRAFT') == 2) then
self:setPackJobText('C', 2)
end
end
------------------------------------------------------------------------------------------------------------
-------------------
-- BG DOWNLOADER --
-------------------
--function outgame:getProgressGroup()
-- --debugInfo("*** 1 ***")
-- local grp = getUI("ui:outgame:charsel:bgd_progress")
-- --debugInfo(tostring(grp))
-- return grp
--end
--
--function outgame:setProgressText(ucstr, color, progress, ellipsis)
-- --debugInfo("*** 2 ***")
-- local text = self:getProgressGroup():find("text")
-- local ellipsisTxt = self:getProgressGroup():find("ellipsis")
-- text.color = color
-- text.uc_hardtext = ucstr
-- if ellipsis then
-- ellipsisTxt.hardtext = ellipsis
-- else
-- ellipsisTxt.hardtext = ""
-- end
-- ellipsisTxt.color = color
-- local progressCtrl = self:getProgressGroup():find("progress")
-- progressCtrl.range = 100
-- progressCtrl.value = progress * 100
-- progressCtrl.active = true
--end
--
--
--local progress progressSymbol = { ".", "..", "..." }
--
---- set patching progression (from 0 to 1)
--function outgame:setPatchProgress(progress)
-- --debugInfo("*** 3 ***")
-- local progressPercentText = string.format("%d%%", 100 * progress)
-- local progressPostfix = math.fmod(os.time(), 3)
-- --debugInfo("Patch in progress : " .. tostring(progress))
-- local progressDate = nltime.getLocalTime() / 500
-- local colValue = math.floor(230 + 24 * math.sin(progressDate))
-- local color = string.format("%d %d %d %d", colValue, colValue, colValue, 255)
-- self:setProgressText(concatUCString(i18n.get("uiBGD_Progress"), ucstring(progressPercentText)), color, progress, progressSymbol[progressPostfix + 1])
--end
--
--function outgame:setPatchSuccess()
-- --debugInfo("*** 4 ***")
-- --debugInfo("Patch up to date")
-- self:setProgressText(i18n.get("uiBGD_PatchUpToDate"), "0 255 0 255", 1)
--end
--
--
--function outgame:setPatchError()
-- --debugInfo("*** 5 ***")
-- --debugInfo("Patch error")
-- self:setProgressText(i18n.get("uiBGD_PatchError"), "255 0 0 255", 0)
--end
--
--function outgame:setNoPatch()
-- --self:getProgressGroup().active = false
--end
------------------------------------------------------------------------------------------------------------
----------------
--LAUNCH GAME --
----------------
function outgame:launchGame()
if not isPlayerSlotNewbieLand(getPlayerSelectedSlot()) then
if not isFullyPatched() then
messageBoxWithHelp(i18n.get("uiBGD_MainlandCharFullPatchNeeded"), "ui:outgame")
return
end
end
runAH(getUICaller(), "proc", "proc_charsel_play")
end

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,934 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include <functional>
#include "child_container.h"
#include "ai_mgr.h"
#include "ai_entity_matrix.h"
#include "ai_player.h"
#include "ai_mgr_pet.h"
#include "ai_grp.h"
#include "ai_mgr_fauna.h"
#include "ai_mgr_npc.h"
#include "ai_bot_npc.h"
#include "ai_grp_npc.h"
#include "ai_grp_pet.h"
#include "ai_script_data_manager.h"
#include "ais_user_models.h"
#include "continent.h"
#include "client_message.h"
#include "ai_outpost.h"
// Georges
#include "nel/georges/u_form_loader.h"
#include "nel/georges/u_form_elm.h"
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_dfn.h"
// Game share
#include "game_share/emote_list_parser.h"
#include "game_share/backup_service_interface.h"
#include "ai_variables.h"
#include "server_share/r2_variables.h"
using namespace NLMISC;
using namespace NLNET;
using namespace std;
using namespace NLGEORGES;
//--------------------------------------------------------------------------
// SINGLETON DATA
//--------------------------------------------------------------------------
CAIS *CAIS::_Instance = NULL;
CRandom CAIS::_random;
const std::string disengageString("DISENGAGE");
const std::string egsString("EGS");
const uint32 Default_MaxPlayers=5000;
const uint32 Default_MaxBotsPet=Default_MaxPlayers*4;
const uint32 Default_MaxBotsFauna=40000;
const uint32 Default_MaxBotsNpc=20000;
const uint32 Default_MaxBotsFx=200;
CAIS &CAIS::instance()
{
if (_Instance == NULL)
{
_Instance = new CAIS();
// init the AI engine
_Instance->initAI();
}
return *_Instance;
}
CAIS::CAIS()
: _PetBotCounter(TotalMaxPet),
_FaunaBotCounter(TotalMaxFauna),
_NpcBotCounter(TotalMaxNpc)
{
// _initialised=false;
_TotalBotsSpawned = 0;
_ClientCreatureDebug=false;
}
void setMaxPetCallBack(IVariable &var)
{
uint32 newMax=NLMISC::safe_cast<CVariable<uint32>*>(&var)->get();
if (CAIS::instanceCreated())
CAIS::instance()._PetBotCounter.setMax(newMax);
}
void setMaxFaunaCallBack(IVariable &var)
{
uint32 newMax=NLMISC::safe_cast<CVariable<uint32>*>(&var)->get();
if (CAIS::instanceCreated())
CAIS::instance()._FaunaBotCounter.setMax(newMax);
}
void setMaxNpcCallBack(IVariable &var)
{
uint32 newMax=NLMISC::safe_cast<CVariable<uint32>*>(&var)->get();
if (CAIS::instanceCreated())
CAIS::instance()._NpcBotCounter.setMax(newMax);
}
CVariable<uint32> TotalMaxPlayer("ai", "NbPlayersLimit", "Security absolute limit to the number of Player", Default_MaxPlayers, 0, true );
CVariable<uint32> TotalMaxPet("ai", "NbPetLimit", "Security absolute limit to the number of Pets", Default_MaxBotsPet, 0, true, setMaxPetCallBack );
CVariable<uint32> TotalMaxFauna("ai", "NbFaunaLimit", "Security absolute limit to the number of Faunas", Default_MaxBotsFauna, 0, true, setMaxFaunaCallBack );
CVariable<uint32> TotalMaxNpc("ai", "NbNpcLimit", "Security absolute limit to the number of Npcs", Default_MaxBotsNpc, 0, true, setMaxNpcCallBack );
CVariable<uint32> TotalMaxFx("ai", "NbFxLimit", "Security absolute limit to the number of Fx", Default_MaxBotsFx, 0, true );
CVariable<string> BotRepopFx("ai", "BotRepopFx", "Fx sheet to use when changing the sheet of a bot", string(), 0, true );
//--------------------------------------------------------------------------
// DATA TABLES FOR ENTITY MATRIX
//--------------------------------------------------------------------------
// a series of tables giving the minimum iterator table forms for entity matrix iterators for all sizes up to 127m
static uint32 EntityMatrixTbl0[] = { 3, 3, 3};
static uint32 EntityMatrixTbl16[] = { 3, 5, 5, 5, 3};
static uint32 EntityMatrixTbl23[] = { 5, 5, 5, 5, 5};
static uint32 EntityMatrixTbl32[] = { 3, 5, 7, 7, 7, 5, 3};
static uint32 EntityMatrixTbl36[] = { 5, 7, 7, 7, 7, 7, 5};
static uint32 EntityMatrixTbl46[] = { 7, 7, 7, 7, 7, 7, 7};
static uint32 EntityMatrixTbl48[] = { 3, 7, 7, 9, 9, 9, 7, 7, 3};
static uint32 EntityMatrixTbl51[] = { 5, 7, 9, 9, 9, 9, 9, 7, 5};
static uint32 EntityMatrixTbl58[] = { 7, 9, 9, 9, 9, 9, 9, 9, 7};
static uint32 EntityMatrixTbl64[] = { 3, 7, 9, 9, 11, 11, 11, 9, 9, 7, 3};
static uint32 EntityMatrixTbl66[] = { 5, 7, 9, 11, 11, 11, 11, 11, 9, 7, 5};
static uint32 EntityMatrixTbl68[] = { 5, 9, 9, 11, 11, 11, 11, 11, 9, 9, 5};
static uint32 EntityMatrixTbl72[] = { 7, 9, 11, 11, 11, 11, 11, 11, 11, 9, 7};
static uint32 EntityMatrixTbl80[] = { 3, 9, 11, 11, 11, 13, 13, 13, 11, 11, 11, 9, 3};
static uint32 EntityMatrixTbl82[] = { 5, 9, 11, 11, 13, 13, 13, 13, 13, 11, 11, 9, 5};
static uint32 EntityMatrixTbl87[] = { 7, 9, 11, 13, 13, 13, 13, 13, 13, 13, 11, 9, 7};
static uint32 EntityMatrixTbl91[] = { 7, 11, 11, 13, 13, 13, 13, 13, 13, 13, 11, 11, 7};
static uint32 EntityMatrixTbl94[] = { 9, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 9};
static uint32 EntityMatrixTbl96[] = { 3, 9, 11, 13, 13, 13, 15, 15, 15, 13, 13, 13, 11, 9, 3};
static uint32 EntityMatrixTbl98[] = { 5, 9, 11, 13, 13, 15, 15, 15, 15, 15, 13, 13, 11, 9, 5};
static uint32 EntityMatrixTbl102[] = { 7, 9, 11, 13, 15, 15, 15, 15, 15, 15, 15, 13, 11, 9, 7};
static uint32 EntityMatrixTbl103[] = { 7, 11, 13, 13, 15, 15, 15, 15, 15, 15, 15, 13, 13, 11, 7};
static uint32 EntityMatrixTbl108[] = { 9, 11, 13, 15, 15, 15, 15, 15, 15, 15, 15, 15, 13, 11, 9};
static uint32 EntityMatrixTbl112[] = { 3, 9, 11, 13, 15, 15, 15, 17, 17, 17, 15, 15, 15, 13, 11, 9, 3};
static uint32 EntityMatrixTbl114[] = { 5, 9, 13, 13, 15, 15, 17, 17, 17, 17, 17, 15, 15, 13, 13, 9, 5};
static uint32 EntityMatrixTbl116[] = { 5, 11, 13, 15, 15, 15, 17, 17, 17, 17, 17, 15, 15, 15, 13, 11, 5};
static uint32 EntityMatrixTbl117[] = { 7, 11, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 11, 7};
static uint32 EntityMatrixTbl122[] = { 9, 11, 13, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 15, 13, 11, 9};
static uint32 EntityMatrixTbl125[] = { 9, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 9};
// a few larger special case matrices
static uint32 EntityMatrixTblUpTo150[] = { 7, 11, 15, 17, 17, 19, 19, 21, 21, 21, 21, 21, 21, 21, 19, 19, 17, 17, 15, 11, 7};
static uint32 EntityMatrixTblUpTo200[] = { 9, 13, 17, 19, 21, 23, 23, 25, 25, 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 25, 23, 23, 21, 19, 17, 13, 9};
static uint32 EntityMatrixTblUpTo250[] = {11, 15, 19, 23, 25, 27, 27, 29, 29, 31, 31, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 31, 31, 29, 29, 27, 27, 25, 23, 19, 15, 11};
static void initLinearMatrixIteratorTables(std::vector<CAIEntityMatrixIteratorTblLinear *> &vect)
{
// initialise the vector with the first table
vect.push_back(new CAIEntityMatrixIteratorTblLinear(&(EntityMatrixTbl0[0]),3));
// local macro undefined at end of function
#define ADD_TBL(d) \
{ \
while (vect.size()<d) \
vect.push_back(vect[vect.size()-1]); \
vect.push_back(new CAIEntityMatrixIteratorTblLinear(EntityMatrixTbl##d,sizeof(EntityMatrixTbl##d)/sizeof(EntityMatrixTbl##d[0]))); \
}
// setup the tables ...
ADD_TBL(16) ADD_TBL(23)
ADD_TBL(32) ADD_TBL(36) ADD_TBL(46)
ADD_TBL(48) ADD_TBL(51) ADD_TBL(58)
ADD_TBL(64) ADD_TBL(66) ADD_TBL(68) ADD_TBL(72)
ADD_TBL(80) ADD_TBL(82) ADD_TBL(87) ADD_TBL(91) ADD_TBL(94)
ADD_TBL(96) ADD_TBL(98) ADD_TBL(102) ADD_TBL(103) ADD_TBL(108)
ADD_TBL(112) ADD_TBL(114) ADD_TBL(116) ADD_TBL(117) ADD_TBL(122) ADD_TBL(125)
#undef ADD_TBL
}
bool CAIS::markTagForDelete(const std::string &filename)
{
const TStringId fileId = CStringMapper::map(filename);
for (CCont<CAIInstance>::iterator it=_AIInstances.begin(), itEnd=_AIInstances.end(); it!=itEnd;++it)
{
// first: tag the dynamic regions in the continents
for_each(it->continents().begin(), it->continents().end(),
bind2nd(mem_fun(&CContinent::markTagForDelete), fileId));
for_each(it->managers().begin(),it->managers().end(),
CAliasTreeRoot::CMarkTagForDelete(fileId));
}
return true;
}
void CAIS::deleteTaggedAlias(const std::string &filename)
{
const TStringId fileId = CStringMapper::map(filename);
FOREACH(it, CCont<CAIInstance>, _AIInstances)
{
// first: tag the dynamic regions in the continents
for_each(it->continents().begin(), it->continents().end(),
bind2nd(mem_fun(&CContinent::deleteTaggedAlias),fileId));
for_each(it->managers().begin(),it->managers().end(),
CAliasTreeRoot::CDeleteTagged<CManager>(it->managers()));
}
}
uint32 CAIS::getEmotNumber(const std::string &name)
{
std::map<std::string, uint32>::iterator it(_EmotNames.find(name));
if (it==_EmotNames.end())
return std::numeric_limits<uint32>::max();
return it->second;
}
bool CAIS::advanceUserTimer (uint32 nbTicks)
{
// for each manager, look for a timer event
for_each(AIList().begin(), AIList().end(), bind2nd(mem_fun(&CAIInstance::advanceUserTimer),nbTicks) );
return true;
}
// initialise the singleton
void CAIS::initAI()
{
// if (_initialised)
// return;
// _initialised=true;
nlinfo("---------- Initialising AI Singleton ----------");
// setup the random number generator
_random.srand( (sint32)NLMISC::CTime::getLocalTime() );
// allocate RAM for the players
// setup the standard iterator tables for scanning the entity matrices
_matrixIterator2x2.push_back(-1,-1); _matrixIterator2x2.push_back(1,0);
_matrixIterator2x2.push_back(-1, 1); _matrixIterator2x2.push_back(1,0);
_matrixIterator3x3.push_back(-1,-1); _matrixIterator3x3.push_back(1,0); _matrixIterator3x3.push_back(1,0);
_matrixIterator3x3.push_back(-2, 1); _matrixIterator3x3.push_back(1,0); _matrixIterator3x3.push_back(1,0);
_matrixIterator3x3.push_back(-2, 1); _matrixIterator3x3.push_back(1,0); _matrixIterator3x3.push_back(1,0);
// setup the set of linear iterator tables for generating visions of given distances
initLinearMatrixIteratorTables(_matrixIteratorsByDistance);
EMOTE_LIST_PARSER::initEmoteList(_EmotNames);
// init the client message callbacks
CAIClientMessages::init();
}
uint32 CAIS::createAIInstance(const std::string &continentName, uint32 instanceNumber)
{
// first, check that an instance with this number is not already running
for (CCont<CAIInstance>::iterator it=_AIInstances.begin(), itEnd=_AIInstances.end();it!=itEnd;++it)
{
if (it->getInstanceNumber()!=instanceNumber)
continue;
nlwarning("CAIS::createAIInstance: instance number %u is already in use, can't create new instance.", instanceNumber);
return std::numeric_limits<uint32>::max();
}
CAIInstance *aii = _AIInstances.addChild(new CAIInstance(this));
// ok, set the continent name and instance number
aii->initInstance(continentName, instanceNumber);
return aii->getChildIndex();
}
void CAIS::destroyAIInstance(uint32 instanceNumber, bool displayWarningIfInstanceNotExist)
{
// this method is not fully tested for a Ryzom shard
// but it should work as expected for a Ring shard
nlassert(IsRingShard.get());
CRefPtr<CAIInstance> aii = getAIInstance(instanceNumber);
if (aii == NULL)
{
if (displayWarningIfInstanceNotExist)
{
nlwarning("AI instance %u does not exist but it was asked to delete here", instanceNumber);
}
return;
}
aii->despawn();
_AIInstances.removeChildByIndex(aii->getChildIndex());
nlassert(aii == NULL);
// notify the EGS
if (EGSHasMirrorReady)
{
CReportAIInstanceDespawnMsg msg;
msg.InstanceNumbers.push_back(instanceNumber);
msg.send("EGS");
}
}
// release the singleton before program exit
void CAIS::release ()
{
// force an update to save the persistent var if needed
updatePersistentVariables();
// erase all ai instance.
AIList().clear();
CAIUserModelManager::getInstance()->destroyInstance();
// release the client message callbacks
CAIClientMessages::release();
// free up the vision matrix iterator tables
if (!_matrixIteratorsByDistance.empty())
{
for (uint i=0;i<_matrixIteratorsByDistance.size();)
{
// erase the iterator table
delete _matrixIteratorsByDistance[i];
// run i forwards past repeated refs to the iterator tbl that we just deleted
for (++i;i<_matrixIteratorsByDistance.size() && _matrixIteratorsByDistance[i]==_matrixIteratorsByDistance[i-1];++i) {}
}
_matrixIteratorsByDistance.clear();
}
_Instance = NULL;
delete this;
}
void CAIS::serviceEvent (const CServiceEvent &info)
{
if (info.getEventType() == CServiceEvent::SERVICE_UP && info.getServiceName() == "EGS")
{
// send the list of available collision data
CReportAICollisionAvailableMsg msg;
msg.ContinentsCollision = CWorldContainer::getContinentList();
msg.send(info.getServiceId());
}
// event on all ai instance
// for_each(_AIInstances.begin(), _AIInstances.end(), bind2nd(mem_fun1(&CAIInstance::serviceEvent), info));
// don't compile coz we need to pass an object and not a reference (info). have to build an object that represents the reference.
FOREACH(it, CCont<CAIInstance>, _AIInstances)
it->serviceEvent (info);
}
//--------------------------------------------------------------------------
// update() & save()
//--------------------------------------------------------------------------
// the update routine called once per tick
// this is the routine that calls the managers' updates
extern void execBufferedCommands();
extern void execNamedEntityChanges();
void CAIS::update()
{
if (!EGSHasMirrorReady)
return;
H_AUTO(AIUpdate);
// Init stat counters
AISStat::countersBegin();
// Execute buffered Task
uint32 tick = CTimeInterface::gameCycle();
_TickedTaskList.execute(tick);
// Execute buffered functions that need to be executed in the correct context
execBufferedCommands();
execNamedEntityChanges();
// Update AI instances
FOREACH(it, CCont<CAIInstance>, CAIS::instance().AIList())
(*it)->CAIInstance::update();
// Send systematic messages to EGS
if (EGSHasMirrorReady)
{
// send the fauna description message to EGS then clear the content.
if (!_FaunaDescriptionList.Bots.empty())
{
nlassert(_FaunaDescriptionList.Bots.size() == _FaunaDescriptionList.GrpAlias.size());
_FaunaDescriptionList.send("EGS");
_FaunaDescriptionList.Bots.clear();
_FaunaDescriptionList.GrpAlias.clear();
}
<<<<<<< HEAD
// send agglomerated ChaScore1 changes
if (!_CreatureChangeChaScore1List.Entities.empty())
{
nlassert(_CreatureChangeChaScore1List.Entities.size()==_CreatureChangeChaScore1List.DeltaChaScore1.size());
_CreatureChangeChaScore1List.send("EGS");
_CreatureChangeChaScore1List.Entities.clear();
_CreatureChangeChaScore1List.DeltaChaScore1.clear();
}
if (!_CreatureChangeMaxChaScore1List.Entities.empty())
{
nlassert(_CreatureChangeMaxChaScore1List.Entities.size()==_CreatureChangeMaxChaScore1List.MaxChaScore1.size());
nlassert(_CreatureChangeMaxChaScore1List.Entities.size()==_CreatureChangeMaxChaScore1List.SetFull.size());
_CreatureChangeMaxChaScore1List.send("EGS");
_CreatureChangeMaxChaScore1List.Entities.clear();
_CreatureChangeMaxChaScore1List.MaxChaScore1.clear();
_CreatureChangeMaxChaScore1List.SetFull.clear();
=======
// send agglomerated hp changes
if (!_CreatureChangeHPList.Entities.empty())
{
nlassert(_CreatureChangeHPList.Entities.size()==_CreatureChangeHPList.DeltaHp.size());
_CreatureChangeHPList.send("EGS");
_CreatureChangeHPList.Entities.clear();
_CreatureChangeHPList.DeltaHp.clear();
}
if (!_CreatureChangeMaxHPList.Entities.empty())
{
nlassert(_CreatureChangeMaxHPList.Entities.size()==_CreatureChangeMaxHPList.MaxHp.size());
nlassert(_CreatureChangeMaxHPList.Entities.size()==_CreatureChangeMaxHPList.SetFull.size());
_CreatureChangeMaxHPList.send("EGS");
_CreatureChangeMaxHPList.Entities.clear();
_CreatureChangeMaxHPList.MaxHp.clear();
_CreatureChangeMaxHPList.SetFull.clear();
>>>>>>> ryzomcore
}
}
//
// update persistent variables every 1024 tick if AI script data manager is flagged
if ((tick & 0x3FF) == 0)
{
updatePersistentVariables();
}
//TODO: UserModelManager must send UserModels to EGS if not done yet
//CAIUserModelManager::getInstance()->sendUserModels();
// Terminate counters and store stats in an accessible place
AISStat::countersEnd();
}
// provoke a general 'save to backup' across the whole service
void CAIS::save()
{
nlinfo("*** save() NOT IMPLEMENTED YET ***");
}
//--------------------------------------------------------------------------
// management of iterator tables for vision matrices
//--------------------------------------------------------------------------
const CAIEntityMatrixIteratorTblLinear* CAIS::bestLinearMatrixIteratorTbl(uint32 distInMeters)
{
#if !FINAL_VERSION
nlassert(!_matrixIteratorsByDistance.empty());
#endif
if (distInMeters >= _matrixIteratorsByDistance.size())
{
//nlwarning("Try to access to a Vision Matrix to far %u the farest is only %u", distInMeters, _matrixIteratorsByDistance.size());
return _matrixIteratorsByDistance.back();
}
return _matrixIteratorsByDistance[distInMeters];
}
int getInt64FromStr (const char* str)
{
if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
return (int) atoiInt64(str+2,16);
return (int) atoiInt64(str,10);
}
// all these dynamics casts can be throwned away ..
CAIInstance* CAIS::tryToGetAIInstance(const char* str)
{
return dynamic_cast<CAIInstance*> (tryToGetEntity(str,CAIS::AI_INSTANCE));
}
CContinent *CAIS::tryToGetContinent (const char *str)
{
return dynamic_cast<CContinent*> (tryToGetEntity(str,CAIS::AI_CONTINENT));
}
CRegion *CAIS::tryToGetRegion (const char *str)
{
return dynamic_cast<CRegion*> (tryToGetEntity(str,CAIS::AI_REGION));
}
CCellZone *CAIS::tryToGetCellZone (const char *str)
{
return dynamic_cast<CCellZone*> (tryToGetEntity(str,CAIS::AI_CELL_ZONE));
}
CFamilyBehavior *CAIS::tryToGetFamilyBehavior (const char *str)
{
return dynamic_cast<CFamilyBehavior*> (tryToGetEntity(str,CAIS::AI_FAMILY_BEHAVIOR));
}
CManager* CAIS::tryToGetManager(const char* str)
{
return dynamic_cast<CManager*> (tryToGetEntity(str,CAIS::AI_MANAGER));
}
CGroup* CAIS::tryToGetGroup(const char* str)
{
return dynamic_cast<CGroup*> (tryToGetEntity(str,CAIS::AI_GROUP));
}
CBot* CAIS::tryToGetBot(const char* str)
{
return dynamic_cast<CBot*> (tryToGetEntity(str,CAIS::AI_BOT));
}
CAIEntity* CAIS::tryToGetAIEntity(const char* str)
{
return dynamic_cast<CAIEntity*> (tryToGetEntity(str));
}
CAIEntityPhysical* CAIS::tryToGetEntityPhysical(const char* str)
{
CEntityId entityId;
entityId.fromString(str);
return CAIS::getEntityPhysical(CMirrors::DataSet->getDataSetRow(entityId));
}
CAIEntity* CAIS::tryToGetEntity(const char* str, TSearchType searchType)
{
CAIInstance *aii = NULL;
CManager *mgr = NULL;
CBot *bot = NULL;
CGroup *grp = NULL;
vector<string> parts;
explode(string(str), string(":"), parts, false);
if (parts.empty() || parts[0].empty())
return NULL;
// skip AIS number if any
if (parts[0].substr(0, 4) == "AIS_")
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// instance index
uint32 index = atoui(parts[0].c_str());
if (index >= CAIS::instance().AIList().size())
goto tryWithEntityId;
aii = CAIS::AIList()[index];
if (!aii)
goto tryWithEntityId;
if (searchType==CAIS::AI_INSTANCE
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return aii;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// branch on static or dynamic system
// manager index
if (parts[0].find("dyn_") == 0)
{
// parse dynamic id
// continent index
index = atoui(parts[0].substr(4).c_str());
if (index >= aii->continents().size())
return NULL;
CContinent *continent = aii->continents()[index];
if (searchType==CAIS::AI_CONTINENT
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return continent;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// region index
index = atoui(parts[0].c_str());
if (index >= continent->regions().size())
return NULL;
CRegion *region = continent->regions()[index];
if (searchType==CAIS::AI_REGION
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return region;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// cellzone index
index = atoui(parts[0].c_str());
if (index >= region->cellZones().size())
return NULL;
CCellZone *cz = region->cellZones()[index];
if (searchType==CAIS::AI_CELL_ZONE
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return cz;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// family behavior index
index = atoui(parts[0].c_str());
if (index >= cz->familyBehaviors().size())
return NULL;
CFamilyBehavior *fb = cz->familyBehaviors()[index];
if (searchType==CAIS::AI_FAMILY_BEHAVIOR
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return fb;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty())
return NULL;
// manager index
if (parts[0] == "npc")
mgr = fb->mgrNpc();
else if (parts[0] == "fauna")
mgr = fb->mgrFauna();
if (!mgr)
return NULL;
if (searchType==CAIS::AI_MANAGER
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1)
|| mgr == NULL)
return mgr;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
}
else
{
// parse static id
// Manager index
index = atoui(parts[0].c_str());
if (index >= aii->managers().size())
return NULL;
mgr = aii->managers()[index];
if (searchType==CAIS::AI_MANAGER
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1)
|| mgr == NULL)
return mgr;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
}
// group index
index = atoui(parts[0].c_str());
if (index >= mgr->groups().size())
return NULL;
grp = mgr->groups()[index];
if (searchType==CAIS::AI_GROUP
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return grp;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// bot index
index = atoui(parts[0].c_str());
if (index >= grp->bots().size())
return NULL;
bot = grp->bots()[index];
if (searchType==CAIS::AI_BOT
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return bot;
// what ?
return NULL;
tryWithEntityId:
CEntityId entityId;
entityId.fromString(str);
if (entityId.isUnknownId())
return NULL;
CCont<CAIInstance>::iterator instanceIt=CAIS::instance().AIList().begin(), instanceItEnd=CAIS::instance().AIList().end();
while (instanceIt!=instanceItEnd)
{
CAIInstance *instancePtr=*instanceIt;
CCont<CManager>::iterator it=instancePtr->managers().begin(), itEnd=instancePtr->managers().end();
while (it!=itEnd)
{
CManager *mgrPtr = *it;
CGroup *grpPtr = mgrPtr->getNextValidGroupChild ();
while (grpPtr)
{
CBot *botPtr = grpPtr->getNextValidBotChild();
while (botPtr)
{
if ( botPtr->isSpawned()
&& botPtr->getSpawnObj()->getEntityId() == entityId)
return dynamic_cast<CAIEntity*> (botPtr);
botPtr = grpPtr->getNextValidBotChild (botPtr);
}
grpPtr=mgrPtr->getNextValidGroupChild (grpPtr);
}
++it;
}
++instanceIt;
}
return NULL;
}
//--------------------------------------------------------------------------
// manageing the set of maps
//--------------------------------------------------------------------------
CAIEntityPhysical *CAIS::getEntityPhysical(const TDataSetRow& row)
{
CHashMap<int,NLMISC::CDbgPtr<CAIEntityPhysical> >::iterator it(_CAIEntityByDataSetRow.find(row.getIndex()));
if (it!=_CAIEntityByDataSetRow.end())
return (*it).second;
else
return NULL;
// the code below generates an error .. :( hu !
}
//-------------------------------------------------------------------
// Interface to bot chat - callbacks called when bots start or
// stop chatting with player(s)
//-------------------------------------------------------------------
void CAIS::beginBotChat(const TDataSetRow &bot,const TDataSetRow &player)
{
#ifdef NL_DEBUG
/// Is this still true?
nlwarning("Chat can't work now as bot are now splitted in persistent and spawnable part. Have to rework on this part.");
#endif
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::beginBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// get a pointer to the player
CBotPlayer* plrPtr = dynamic_cast<CBotPlayer*>(CAIS::getEntityPhysical(player));
if (plrPtr==NULL)
{
// nlwarning("CAIS::beginBotChat(): Bot chat message identifies an unknown player!!!");
return;
}
// have the bot register the chat
botNpc->beginBotChat(plrPtr);
}
void CAIS::endBotChat(const TDataSetRow &bot, const TDataSetRow &player)
{
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::endBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// get a pointer to the player
CBotPlayer* plrPtr = dynamic_cast<CBotPlayer*>(CAIS::getEntityPhysical(player));
if (!plrPtr)
{
// nlwarning("CAIS::endBotChat(): Bot chat message identifies an unknown player!!!");
return;
}
// have the bot register the chat end
botNpc->endBotChat(plrPtr);
}
void CAIS::beginDynChat(const TDataSetRow &bot)
{
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::beginBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// have the bot register the chat
botNpc->beginDynChat();
nldebug( "DYNCHT: E%u: %u dyn chats", bot.getIndex(), botNpc->getNbActiveDynChats() );
}
void CAIS::endDynChat(const TDataSetRow &bot)
{
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::endBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// have the bot register the chat end
botNpc->endDynChat();
nldebug( "DYNCHT: E%u: %u dyn chats", bot.getIndex(), botNpc->getNbActiveDynChats() );
}
void CAIPlaceXYR::display(CStringWriter &stringWriter) const
{
stringWriter.append("XYR: ("+_pos.x().toString()
+" "
+_pos.y().toString()
+" "+toString(_pos.h())
+") Radius "
+toString(_radius)
+" "
+getName());
// nlinfo("XYR: (%s,%s,%d) x %f :%s",_pos.x().toString().c_str(),_pos.y().toString().c_str(),_pos.h(),_radius,getName().c_str());
}
void CAIS::warnBadInstanceMsgImp(const std::string &serviceName, TServiceId serviceId, CWarnBadInstanceMsgImp &msg)
{
// EGS says that an instance is spoofing an instance number or using a bad static instance number/continent name association.
// we must despawn/delete the aiinstance
FOREACH(it, CCont<CAIInstance>, _AIInstances)
{
if ((*it)->getInstanceNumber()!=msg.InstanceNumber)
continue;
// ok, we found the bad guy !
nlwarning("CAIS::warnBadInstanceMsgImp: despawning AIInstance %u, instance number %u, continent '%s'",
(*it)->getChildIndex(), msg.InstanceNumber, (*it)->getContinentName().c_str());
_AIInstances.removeChildByIndex((*it)->getChildIndex());
return;
}
// not found
nlwarning("CAIS::warnBadInstanceMsgImp: can't find AIInstance with instance number %u ! Can't despawn it", msg.InstanceNumber);
}
void CAIS::updatePersistentVariables()
{
if (CAIScriptDataManager::getInstance()->needsPersistentVarUpdate() == true)
{
// sending data to bs
CPersistentDataRecord pdr("AiTokenFamily");
CAIScriptDataManager::getInstance()->getPersistentVariables().store(pdr);
uint32 bufSize= pdr.totalDataSize();
vector<char> buffer;
buffer.resize(bufSize);
pdr.toBuffer(&buffer[0],bufSize);
CBackupMsgSaveFile msg( CAIScriptDataManager::getInstance()->makePdrFileName(), CBackupMsgSaveFile::SaveFile, Bsi );
msg.DataMsg.serialBuffer((uint8*)&buffer[0], bufSize);
Bsi.sendFile( msg );
CAIScriptDataManager::getInstance()->clearDirtyFlag();
}
}
CAIInstance *CAIS::getAIInstance(uint32 instanceNumber)
{
FOREACH(it, CCont<CAIInstance>, _AIInstances)
{
if ((*it)->getInstanceNumber()==instanceNumber)
return *it;
}
return NULL;
}

View file

@ -1,915 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include <functional>
#include "child_container.h"
#include "ai_mgr.h"
#include "ai_entity_matrix.h"
#include "ai_player.h"
#include "ai_mgr_pet.h"
#include "ai_grp.h"
#include "ai_mgr_fauna.h"
#include "ai_mgr_npc.h"
#include "ai_bot_npc.h"
#include "ai_grp_npc.h"
#include "ai_grp_pet.h"
#include "ai_script_data_manager.h"
#include "ais_user_models.h"
#include "continent.h"
#include "client_message.h"
#include "ai_outpost.h"
// Georges
#include "nel/georges/u_form_loader.h"
#include "nel/georges/u_form_elm.h"
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_dfn.h"
// Game share
#include "game_share/emote_list_parser.h"
#include "game_share/backup_service_interface.h"
#include "ai_variables.h"
#include "server_share/r2_variables.h"
using namespace NLMISC;
using namespace NLNET;
using namespace std;
using namespace NLGEORGES;
//--------------------------------------------------------------------------
// SINGLETON DATA
//--------------------------------------------------------------------------
CAIS *CAIS::_Instance = NULL;
CRandom CAIS::_random;
const std::string disengageString("DISENGAGE");
const std::string egsString("EGS");
const uint32 Default_MaxPlayers=5000;
const uint32 Default_MaxBotsPet=Default_MaxPlayers*4;
const uint32 Default_MaxBotsFauna=40000;
const uint32 Default_MaxBotsNpc=20000;
const uint32 Default_MaxBotsFx=200;
CAIS &CAIS::instance()
{
if (_Instance == NULL)
{
_Instance = new CAIS();
// init the AI engine
_Instance->initAI();
}
return *_Instance;
}
CAIS::CAIS()
: _PetBotCounter(TotalMaxPet),
_FaunaBotCounter(TotalMaxFauna),
_NpcBotCounter(TotalMaxNpc)
{
// _initialised=false;
_TotalBotsSpawned = 0;
_ClientCreatureDebug=false;
}
void setMaxPetCallBack(IVariable &var)
{
uint32 newMax=NLMISC::safe_cast<CVariable<uint32>*>(&var)->get();
if (CAIS::instanceCreated())
CAIS::instance()._PetBotCounter.setMax(newMax);
}
void setMaxFaunaCallBack(IVariable &var)
{
uint32 newMax=NLMISC::safe_cast<CVariable<uint32>*>(&var)->get();
if (CAIS::instanceCreated())
CAIS::instance()._FaunaBotCounter.setMax(newMax);
}
void setMaxNpcCallBack(IVariable &var)
{
uint32 newMax=NLMISC::safe_cast<CVariable<uint32>*>(&var)->get();
if (CAIS::instanceCreated())
CAIS::instance()._NpcBotCounter.setMax(newMax);
}
CVariable<uint32> TotalMaxPlayer("ai", "NbPlayersLimit", "Security absolute limit to the number of Player", Default_MaxPlayers, 0, true );
CVariable<uint32> TotalMaxPet("ai", "NbPetLimit", "Security absolute limit to the number of Pets", Default_MaxBotsPet, 0, true, setMaxPetCallBack );
CVariable<uint32> TotalMaxFauna("ai", "NbFaunaLimit", "Security absolute limit to the number of Faunas", Default_MaxBotsFauna, 0, true, setMaxFaunaCallBack );
CVariable<uint32> TotalMaxNpc("ai", "NbNpcLimit", "Security absolute limit to the number of Npcs", Default_MaxBotsNpc, 0, true, setMaxNpcCallBack );
CVariable<uint32> TotalMaxFx("ai", "NbFxLimit", "Security absolute limit to the number of Fx", Default_MaxBotsFx, 0, true );
CVariable<string> BotRepopFx("ai", "BotRepopFx", "Fx sheet to use when changing the sheet of a bot", string(), 0, true );
//--------------------------------------------------------------------------
// DATA TABLES FOR ENTITY MATRIX
//--------------------------------------------------------------------------
// a series of tables giving the minimum iterator table forms for entity matrix iterators for all sizes up to 127m
static uint32 EntityMatrixTbl0[] = { 3, 3, 3};
static uint32 EntityMatrixTbl16[] = { 3, 5, 5, 5, 3};
static uint32 EntityMatrixTbl23[] = { 5, 5, 5, 5, 5};
static uint32 EntityMatrixTbl32[] = { 3, 5, 7, 7, 7, 5, 3};
static uint32 EntityMatrixTbl36[] = { 5, 7, 7, 7, 7, 7, 5};
static uint32 EntityMatrixTbl46[] = { 7, 7, 7, 7, 7, 7, 7};
static uint32 EntityMatrixTbl48[] = { 3, 7, 7, 9, 9, 9, 7, 7, 3};
static uint32 EntityMatrixTbl51[] = { 5, 7, 9, 9, 9, 9, 9, 7, 5};
static uint32 EntityMatrixTbl58[] = { 7, 9, 9, 9, 9, 9, 9, 9, 7};
static uint32 EntityMatrixTbl64[] = { 3, 7, 9, 9, 11, 11, 11, 9, 9, 7, 3};
static uint32 EntityMatrixTbl66[] = { 5, 7, 9, 11, 11, 11, 11, 11, 9, 7, 5};
static uint32 EntityMatrixTbl68[] = { 5, 9, 9, 11, 11, 11, 11, 11, 9, 9, 5};
static uint32 EntityMatrixTbl72[] = { 7, 9, 11, 11, 11, 11, 11, 11, 11, 9, 7};
static uint32 EntityMatrixTbl80[] = { 3, 9, 11, 11, 11, 13, 13, 13, 11, 11, 11, 9, 3};
static uint32 EntityMatrixTbl82[] = { 5, 9, 11, 11, 13, 13, 13, 13, 13, 11, 11, 9, 5};
static uint32 EntityMatrixTbl87[] = { 7, 9, 11, 13, 13, 13, 13, 13, 13, 13, 11, 9, 7};
static uint32 EntityMatrixTbl91[] = { 7, 11, 11, 13, 13, 13, 13, 13, 13, 13, 11, 11, 7};
static uint32 EntityMatrixTbl94[] = { 9, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 9};
static uint32 EntityMatrixTbl96[] = { 3, 9, 11, 13, 13, 13, 15, 15, 15, 13, 13, 13, 11, 9, 3};
static uint32 EntityMatrixTbl98[] = { 5, 9, 11, 13, 13, 15, 15, 15, 15, 15, 13, 13, 11, 9, 5};
static uint32 EntityMatrixTbl102[] = { 7, 9, 11, 13, 15, 15, 15, 15, 15, 15, 15, 13, 11, 9, 7};
static uint32 EntityMatrixTbl103[] = { 7, 11, 13, 13, 15, 15, 15, 15, 15, 15, 15, 13, 13, 11, 7};
static uint32 EntityMatrixTbl108[] = { 9, 11, 13, 15, 15, 15, 15, 15, 15, 15, 15, 15, 13, 11, 9};
static uint32 EntityMatrixTbl112[] = { 3, 9, 11, 13, 15, 15, 15, 17, 17, 17, 15, 15, 15, 13, 11, 9, 3};
static uint32 EntityMatrixTbl114[] = { 5, 9, 13, 13, 15, 15, 17, 17, 17, 17, 17, 15, 15, 13, 13, 9, 5};
static uint32 EntityMatrixTbl116[] = { 5, 11, 13, 15, 15, 15, 17, 17, 17, 17, 17, 15, 15, 15, 13, 11, 5};
static uint32 EntityMatrixTbl117[] = { 7, 11, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 11, 7};
static uint32 EntityMatrixTbl122[] = { 9, 11, 13, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 15, 13, 11, 9};
static uint32 EntityMatrixTbl125[] = { 9, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 9};
// a few larger special case matrices
static uint32 EntityMatrixTblUpTo150[] = { 7, 11, 15, 17, 17, 19, 19, 21, 21, 21, 21, 21, 21, 21, 19, 19, 17, 17, 15, 11, 7};
static uint32 EntityMatrixTblUpTo200[] = { 9, 13, 17, 19, 21, 23, 23, 25, 25, 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 25, 23, 23, 21, 19, 17, 13, 9};
static uint32 EntityMatrixTblUpTo250[] = {11, 15, 19, 23, 25, 27, 27, 29, 29, 31, 31, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 31, 31, 29, 29, 27, 27, 25, 23, 19, 15, 11};
static void initLinearMatrixIteratorTables(std::vector<CAIEntityMatrixIteratorTblLinear *> &vect)
{
// initialise the vector with the first table
vect.push_back(new CAIEntityMatrixIteratorTblLinear(&(EntityMatrixTbl0[0]),3));
// local macro undefined at end of function
#define ADD_TBL(d) \
{ \
while (vect.size()<d) \
vect.push_back(vect[vect.size()-1]); \
vect.push_back(new CAIEntityMatrixIteratorTblLinear(EntityMatrixTbl##d,sizeof(EntityMatrixTbl##d)/sizeof(EntityMatrixTbl##d[0]))); \
}
// setup the tables ...
ADD_TBL(16) ADD_TBL(23)
ADD_TBL(32) ADD_TBL(36) ADD_TBL(46)
ADD_TBL(48) ADD_TBL(51) ADD_TBL(58)
ADD_TBL(64) ADD_TBL(66) ADD_TBL(68) ADD_TBL(72)
ADD_TBL(80) ADD_TBL(82) ADD_TBL(87) ADD_TBL(91) ADD_TBL(94)
ADD_TBL(96) ADD_TBL(98) ADD_TBL(102) ADD_TBL(103) ADD_TBL(108)
ADD_TBL(112) ADD_TBL(114) ADD_TBL(116) ADD_TBL(117) ADD_TBL(122) ADD_TBL(125)
#undef ADD_TBL
}
bool CAIS::markTagForDelete(const std::string &filename)
{
const TStringId fileId = CStringMapper::map(filename);
for (CCont<CAIInstance>::iterator it=_AIInstances.begin(), itEnd=_AIInstances.end(); it!=itEnd;++it)
{
// first: tag the dynamic regions in the continents
for_each(it->continents().begin(), it->continents().end(),
bind2nd(mem_fun(&CContinent::markTagForDelete), fileId));
for_each(it->managers().begin(),it->managers().end(),
CAliasTreeRoot::CMarkTagForDelete(fileId));
}
return true;
}
void CAIS::deleteTaggedAlias(const std::string &filename)
{
const TStringId fileId = CStringMapper::map(filename);
FOREACH(it, CCont<CAIInstance>, _AIInstances)
{
// first: tag the dynamic regions in the continents
for_each(it->continents().begin(), it->continents().end(),
bind2nd(mem_fun(&CContinent::deleteTaggedAlias),fileId));
for_each(it->managers().begin(),it->managers().end(),
CAliasTreeRoot::CDeleteTagged<CManager>(it->managers()));
}
}
uint32 CAIS::getEmotNumber(const std::string &name)
{
std::map<std::string, uint32>::iterator it(_EmotNames.find(name));
if (it==_EmotNames.end())
return std::numeric_limits<uint32>::max();
return it->second;
}
bool CAIS::advanceUserTimer (uint32 nbTicks)
{
// for each manager, look for a timer event
for_each(AIList().begin(), AIList().end(), bind2nd(mem_fun(&CAIInstance::advanceUserTimer),nbTicks) );
return true;
}
// initialise the singleton
void CAIS::initAI()
{
// if (_initialised)
// return;
// _initialised=true;
nlinfo("---------- Initialising AI Singleton ----------");
// setup the random number generator
_random.srand( (sint32)NLMISC::CTime::getLocalTime() );
// allocate RAM for the players
// setup the standard iterator tables for scanning the entity matrices
_matrixIterator2x2.push_back(-1,-1); _matrixIterator2x2.push_back(1,0);
_matrixIterator2x2.push_back(-1, 1); _matrixIterator2x2.push_back(1,0);
_matrixIterator3x3.push_back(-1,-1); _matrixIterator3x3.push_back(1,0); _matrixIterator3x3.push_back(1,0);
_matrixIterator3x3.push_back(-2, 1); _matrixIterator3x3.push_back(1,0); _matrixIterator3x3.push_back(1,0);
_matrixIterator3x3.push_back(-2, 1); _matrixIterator3x3.push_back(1,0); _matrixIterator3x3.push_back(1,0);
// setup the set of linear iterator tables for generating visions of given distances
initLinearMatrixIteratorTables(_matrixIteratorsByDistance);
EMOTE_LIST_PARSER::initEmoteList(_EmotNames);
// init the client message callbacks
CAIClientMessages::init();
}
uint32 CAIS::createAIInstance(const std::string &continentName, uint32 instanceNumber)
{
// first, check that an instance with this number is not already running
for (CCont<CAIInstance>::iterator it=_AIInstances.begin(), itEnd=_AIInstances.end();it!=itEnd;++it)
{
if (it->getInstanceNumber()!=instanceNumber)
continue;
nlwarning("CAIS::createAIInstance: instance number %u is already in use, can't create new instance.", instanceNumber);
return std::numeric_limits<uint32>::max();
}
CAIInstance *aii = _AIInstances.addChild(new CAIInstance(this));
// ok, set the continent name and instance number
aii->initInstance(continentName, instanceNumber);
return aii->getChildIndex();
}
void CAIS::destroyAIInstance(uint32 instanceNumber, bool displayWarningIfInstanceNotExist)
{
// this method is not fully tested for a Ryzom shard
// but it should work as expected for a Ring shard
nlassert(IsRingShard.get());
CRefPtr<CAIInstance> aii = getAIInstance(instanceNumber);
if (aii == NULL)
{
if (displayWarningIfInstanceNotExist)
{
nlwarning("AI instance %u does not exist but it was asked to delete here", instanceNumber);
}
return;
}
aii->despawn();
_AIInstances.removeChildByIndex(aii->getChildIndex());
nlassert(aii == NULL);
// notify the EGS
if (EGSHasMirrorReady)
{
CReportAIInstanceDespawnMsg msg;
msg.InstanceNumbers.push_back(instanceNumber);
msg.send("EGS");
}
}
// release the singleton before program exit
void CAIS::release ()
{
// force an update to save the persistent var if needed
updatePersistentVariables();
// erase all ai instance.
AIList().clear();
CAIUserModelManager::getInstance()->destroyInstance();
// release the client message callbacks
CAIClientMessages::release();
// free up the vision matrix iterator tables
if (!_matrixIteratorsByDistance.empty())
{
for (uint i=0;i<_matrixIteratorsByDistance.size();)
{
// erase the iterator table
delete _matrixIteratorsByDistance[i];
// run i forwards past repeated refs to the iterator tbl that we just deleted
for (++i;i<_matrixIteratorsByDistance.size() && _matrixIteratorsByDistance[i]==_matrixIteratorsByDistance[i-1];++i) {}
}
_matrixIteratorsByDistance.clear();
}
_Instance = NULL;
delete this;
}
void CAIS::serviceEvent (const CServiceEvent &info)
{
if (info.getEventType() == CServiceEvent::SERVICE_UP && info.getServiceName() == "EGS")
{
// send the list of available collision data
CReportAICollisionAvailableMsg msg;
msg.ContinentsCollision = CWorldContainer::getContinentList();
msg.send(info.getServiceId());
}
// event on all ai instance
// for_each(_AIInstances.begin(), _AIInstances.end(), bind2nd(mem_fun1(&CAIInstance::serviceEvent), info));
// don't compile coz we need to pass an object and not a reference (info). have to build an object that represents the reference.
FOREACH(it, CCont<CAIInstance>, _AIInstances)
it->serviceEvent (info);
}
//--------------------------------------------------------------------------
// update() & save()
//--------------------------------------------------------------------------
// the update routine called once per tick
// this is the routine that calls the managers' updates
extern void execBufferedCommands();
extern void execNamedEntityChanges();
void CAIS::update()
{
if (!EGSHasMirrorReady)
return;
H_AUTO(AIUpdate);
// Init stat counters
AISStat::countersBegin();
// Execute buffered Task
uint32 tick = CTimeInterface::gameCycle();
_TickedTaskList.execute(tick);
// Execute buffered functions that need to be executed in the correct context
execBufferedCommands();
execNamedEntityChanges();
// Update AI instances
FOREACH(it, CCont<CAIInstance>, CAIS::instance().AIList())
(*it)->CAIInstance::update();
// Send systematic messages to EGS
if (EGSHasMirrorReady)
{
// send the fauna description message to EGS then clear the content.
if (!_FaunaDescriptionList.Bots.empty())
{
nlassert(_FaunaDescriptionList.Bots.size() == _FaunaDescriptionList.GrpAlias.size());
_FaunaDescriptionList.send("EGS");
_FaunaDescriptionList.Bots.clear();
_FaunaDescriptionList.GrpAlias.clear();
}
// send agglomerated ChaScore1 changes
if (!_CreatureChangeChaScore1List.Entities.empty())
{
nlassert(_CreatureChangeChaScore1List.Entities.size()==_CreatureChangeChaScore1List.DeltaChaScore1.size());
_CreatureChangeChaScore1List.send("EGS");
_CreatureChangeChaScore1List.Entities.clear();
_CreatureChangeChaScore1List.DeltaChaScore1.clear();
}
if (!_CreatureChangeMaxChaScore1List.Entities.empty())
{
nlassert(_CreatureChangeMaxChaScore1List.Entities.size()==_CreatureChangeMaxChaScore1List.MaxChaScore1.size());
nlassert(_CreatureChangeMaxChaScore1List.Entities.size()==_CreatureChangeMaxChaScore1List.SetFull.size());
_CreatureChangeMaxChaScore1List.send("EGS");
_CreatureChangeMaxChaScore1List.Entities.clear();
_CreatureChangeMaxChaScore1List.MaxChaScore1.clear();
_CreatureChangeMaxChaScore1List.SetFull.clear();
}
}
//
// update persistent variables every 1024 tick if AI script data manager is flagged
if ((tick & 0x3FF) == 0)
{
updatePersistentVariables();
}
//TODO: UserModelManager must send UserModels to EGS if not done yet
//CAIUserModelManager::getInstance()->sendUserModels();
// Terminate counters and store stats in an accessible place
AISStat::countersEnd();
}
// provoke a general 'save to backup' across the whole service
void CAIS::save()
{
nlinfo("*** save() NOT IMPLEMENTED YET ***");
}
//--------------------------------------------------------------------------
// management of iterator tables for vision matrices
//--------------------------------------------------------------------------
const CAIEntityMatrixIteratorTblLinear* CAIS::bestLinearMatrixIteratorTbl(uint32 distInMeters)
{
#if !FINAL_VERSION
nlassert(!_matrixIteratorsByDistance.empty());
#endif
if (distInMeters >= _matrixIteratorsByDistance.size())
{
//nlwarning("Try to access to a Vision Matrix to far %u the farest is only %u", distInMeters, _matrixIteratorsByDistance.size());
return _matrixIteratorsByDistance.back();
}
return _matrixIteratorsByDistance[distInMeters];
}
int getInt64FromStr (const char* str)
{
if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
return (int) atoiInt64(str+2,16);
return (int) atoiInt64(str,10);
}
// all these dynamics casts can be throwned away ..
CAIInstance* CAIS::tryToGetAIInstance(const char* str)
{
return dynamic_cast<CAIInstance*> (tryToGetEntity(str,CAIS::AI_INSTANCE));
}
CContinent *CAIS::tryToGetContinent (const char *str)
{
return dynamic_cast<CContinent*> (tryToGetEntity(str,CAIS::AI_CONTINENT));
}
CRegion *CAIS::tryToGetRegion (const char *str)
{
return dynamic_cast<CRegion*> (tryToGetEntity(str,CAIS::AI_REGION));
}
CCellZone *CAIS::tryToGetCellZone (const char *str)
{
return dynamic_cast<CCellZone*> (tryToGetEntity(str,CAIS::AI_CELL_ZONE));
}
CFamilyBehavior *CAIS::tryToGetFamilyBehavior (const char *str)
{
return dynamic_cast<CFamilyBehavior*> (tryToGetEntity(str,CAIS::AI_FAMILY_BEHAVIOR));
}
CManager* CAIS::tryToGetManager(const char* str)
{
return dynamic_cast<CManager*> (tryToGetEntity(str,CAIS::AI_MANAGER));
}
CGroup* CAIS::tryToGetGroup(const char* str)
{
return dynamic_cast<CGroup*> (tryToGetEntity(str,CAIS::AI_GROUP));
}
CBot* CAIS::tryToGetBot(const char* str)
{
return dynamic_cast<CBot*> (tryToGetEntity(str,CAIS::AI_BOT));
}
CAIEntity* CAIS::tryToGetAIEntity(const char* str)
{
return dynamic_cast<CAIEntity*> (tryToGetEntity(str));
}
CAIEntityPhysical* CAIS::tryToGetEntityPhysical(const char* str)
{
CEntityId entityId;
entityId.fromString(str);
return CAIS::getEntityPhysical(CMirrors::DataSet->getDataSetRow(entityId));
}
CAIEntity* CAIS::tryToGetEntity(const char* str, TSearchType searchType)
{
CAIInstance *aii = NULL;
CManager *mgr = NULL;
CBot *bot = NULL;
CGroup *grp = NULL;
vector<string> parts;
explode(string(str), string(":"), parts, false);
if (parts.empty() || parts[0].empty())
return NULL;
// skip AIS number if any
if (parts[0].substr(0, 4) == "AIS_")
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// instance index
uint32 index = atoui(parts[0].c_str());
if (index >= CAIS::instance().AIList().size())
goto tryWithEntityId;
aii = CAIS::AIList()[index];
if (!aii)
goto tryWithEntityId;
if (searchType==CAIS::AI_INSTANCE
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return aii;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// branch on static or dynamic system
// manager index
if (parts[0].find("dyn_") == 0)
{
// parse dynamic id
// continent index
index = atoui(parts[0].substr(4).c_str());
if (index >= aii->continents().size())
return NULL;
CContinent *continent = aii->continents()[index];
if (searchType==CAIS::AI_CONTINENT
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return continent;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// region index
index = atoui(parts[0].c_str());
if (index >= continent->regions().size())
return NULL;
CRegion *region = continent->regions()[index];
if (searchType==CAIS::AI_REGION
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return region;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// cellzone index
index = atoui(parts[0].c_str());
if (index >= region->cellZones().size())
return NULL;
CCellZone *cz = region->cellZones()[index];
if (searchType==CAIS::AI_CELL_ZONE
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return cz;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// family behavior index
index = atoui(parts[0].c_str());
if (index >= cz->familyBehaviors().size())
return NULL;
CFamilyBehavior *fb = cz->familyBehaviors()[index];
if (searchType==CAIS::AI_FAMILY_BEHAVIOR
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return fb;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty())
return NULL;
// manager index
if (parts[0] == "npc")
mgr = fb->mgrNpc();
else if (parts[0] == "fauna")
mgr = fb->mgrFauna();
if (!mgr)
return NULL;
if (searchType==CAIS::AI_MANAGER
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1)
|| mgr == NULL)
return mgr;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
}
else
{
// parse static id
// Manager index
index = atoui(parts[0].c_str());
if (index >= aii->managers().size())
return NULL;
mgr = aii->managers()[index];
if (searchType==CAIS::AI_MANAGER
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1)
|| mgr == NULL)
return mgr;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
}
// group index
index = atoui(parts[0].c_str());
if (index >= mgr->groups().size())
return NULL;
grp = mgr->groups()[index];
if (searchType==CAIS::AI_GROUP
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return grp;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// bot index
index = atoui(parts[0].c_str());
if (index >= grp->bots().size())
return NULL;
bot = grp->bots()[index];
if (searchType==CAIS::AI_BOT
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return bot;
// what ?
return NULL;
tryWithEntityId:
CEntityId entityId;
entityId.fromString(str);
if (entityId.isUnknownId())
return NULL;
CCont<CAIInstance>::iterator instanceIt=CAIS::instance().AIList().begin(), instanceItEnd=CAIS::instance().AIList().end();
while (instanceIt!=instanceItEnd)
{
CAIInstance *instancePtr=*instanceIt;
CCont<CManager>::iterator it=instancePtr->managers().begin(), itEnd=instancePtr->managers().end();
while (it!=itEnd)
{
CManager *mgrPtr = *it;
CGroup *grpPtr = mgrPtr->getNextValidGroupChild ();
while (grpPtr)
{
CBot *botPtr = grpPtr->getNextValidBotChild();
while (botPtr)
{
if ( botPtr->isSpawned()
&& botPtr->getSpawnObj()->getEntityId() == entityId)
return dynamic_cast<CAIEntity*> (botPtr);
botPtr = grpPtr->getNextValidBotChild (botPtr);
}
grpPtr=mgrPtr->getNextValidGroupChild (grpPtr);
}
++it;
}
++instanceIt;
}
return NULL;
}
//--------------------------------------------------------------------------
// manageing the set of maps
//--------------------------------------------------------------------------
CAIEntityPhysical *CAIS::getEntityPhysical(const TDataSetRow& row)
{
CHashMap<int,NLMISC::CDbgPtr<CAIEntityPhysical> >::iterator it(_CAIEntityByDataSetRow.find(row.getIndex()));
if (it!=_CAIEntityByDataSetRow.end())
return (*it).second;
else
return NULL;
// the code below generates an error .. :( hu !
}
//-------------------------------------------------------------------
// Interface to bot chat - callbacks called when bots start or
// stop chatting with player(s)
//-------------------------------------------------------------------
void CAIS::beginBotChat(const TDataSetRow &bot,const TDataSetRow &player)
{
#ifdef NL_DEBUG
/// Is this still true?
nlwarning("Chat can't work now as bot are now splitted in persistent and spawnable part. Have to rework on this part.");
#endif
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::beginBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// get a pointer to the player
CBotPlayer* plrPtr = dynamic_cast<CBotPlayer*>(CAIS::getEntityPhysical(player));
if (plrPtr==NULL)
{
// nlwarning("CAIS::beginBotChat(): Bot chat message identifies an unknown player!!!");
return;
}
// have the bot register the chat
botNpc->beginBotChat(plrPtr);
}
void CAIS::endBotChat(const TDataSetRow &bot, const TDataSetRow &player)
{
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::endBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// get a pointer to the player
CBotPlayer* plrPtr = dynamic_cast<CBotPlayer*>(CAIS::getEntityPhysical(player));
if (!plrPtr)
{
// nlwarning("CAIS::endBotChat(): Bot chat message identifies an unknown player!!!");
return;
}
// have the bot register the chat end
botNpc->endBotChat(plrPtr);
}
void CAIS::beginDynChat(const TDataSetRow &bot)
{
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::beginBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// have the bot register the chat
botNpc->beginDynChat();
nldebug( "DYNCHT: E%u: %u dyn chats", bot.getIndex(), botNpc->getNbActiveDynChats() );
}
void CAIS::endDynChat(const TDataSetRow &bot)
{
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::endBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// have the bot register the chat end
botNpc->endDynChat();
nldebug( "DYNCHT: E%u: %u dyn chats", bot.getIndex(), botNpc->getNbActiveDynChats() );
}
void CAIPlaceXYR::display(CStringWriter &stringWriter) const
{
stringWriter.append("XYR: ("+_pos.x().toString()
+" "
+_pos.y().toString()
+" "+toString(_pos.h())
+") Radius "
+toString(_radius)
+" "
+getName());
// nlinfo("XYR: (%s,%s,%d) x %f :%s",_pos.x().toString().c_str(),_pos.y().toString().c_str(),_pos.h(),_radius,getName().c_str());
}
void CAIS::warnBadInstanceMsgImp(const std::string &serviceName, TServiceId serviceId, CWarnBadInstanceMsgImp &msg)
{
// EGS says that an instance is spoofing an instance number or using a bad static instance number/continent name association.
// we must despawn/delete the aiinstance
FOREACH(it, CCont<CAIInstance>, _AIInstances)
{
if ((*it)->getInstanceNumber()!=msg.InstanceNumber)
continue;
// ok, we found the bad guy !
nlwarning("CAIS::warnBadInstanceMsgImp: despawning AIInstance %u, instance number %u, continent '%s'",
(*it)->getChildIndex(), msg.InstanceNumber, (*it)->getContinentName().c_str());
_AIInstances.removeChildByIndex((*it)->getChildIndex());
return;
}
// not found
nlwarning("CAIS::warnBadInstanceMsgImp: can't find AIInstance with instance number %u ! Can't despawn it", msg.InstanceNumber);
}
void CAIS::updatePersistentVariables()
{
if (CAIScriptDataManager::getInstance()->needsPersistentVarUpdate() == true)
{
// sending data to bs
CPersistentDataRecord pdr("AiTokenFamily");
CAIScriptDataManager::getInstance()->getPersistentVariables().store(pdr);
uint32 bufSize= pdr.totalDataSize();
vector<char> buffer;
buffer.resize(bufSize);
pdr.toBuffer(&buffer[0],bufSize);
CBackupMsgSaveFile msg( CAIScriptDataManager::getInstance()->makePdrFileName(), CBackupMsgSaveFile::SaveFile, Bsi );
msg.DataMsg.serialBuffer((uint8*)&buffer[0], bufSize);
Bsi.sendFile( msg );
CAIScriptDataManager::getInstance()->clearDirtyFlag();
}
}
CAIInstance *CAIS::getAIInstance(uint32 instanceNumber)
{
FOREACH(it, CCont<CAIInstance>, _AIInstances)
{
if ((*it)->getInstanceNumber()==instanceNumber)
return *it;
}
return NULL;
}

View file

@ -1,915 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include <functional>
#include "child_container.h"
#include "ai_mgr.h"
#include "ai_entity_matrix.h"
#include "ai_player.h"
#include "ai_mgr_pet.h"
#include "ai_grp.h"
#include "ai_mgr_fauna.h"
#include "ai_mgr_npc.h"
#include "ai_bot_npc.h"
#include "ai_grp_npc.h"
#include "ai_grp_pet.h"
#include "ai_script_data_manager.h"
#include "ais_user_models.h"
#include "continent.h"
#include "client_message.h"
#include "ai_outpost.h"
// Georges
#include "nel/georges/u_form_loader.h"
#include "nel/georges/u_form_elm.h"
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_dfn.h"
// Game share
#include "game_share/emote_list_parser.h"
#include "game_share/backup_service_interface.h"
#include "ai_variables.h"
#include "server_share/r2_variables.h"
using namespace NLMISC;
using namespace NLNET;
using namespace std;
using namespace NLGEORGES;
//--------------------------------------------------------------------------
// SINGLETON DATA
//--------------------------------------------------------------------------
CAIS *CAIS::_Instance = NULL;
CRandom CAIS::_random;
const std::string disengageString("DISENGAGE");
const std::string egsString("EGS");
const uint32 Default_MaxPlayers=5000;
const uint32 Default_MaxBotsPet=Default_MaxPlayers*4;
const uint32 Default_MaxBotsFauna=40000;
const uint32 Default_MaxBotsNpc=20000;
const uint32 Default_MaxBotsFx=200;
CAIS &CAIS::instance()
{
if (_Instance == NULL)
{
_Instance = new CAIS();
// init the AI engine
_Instance->initAI();
}
return *_Instance;
}
CAIS::CAIS()
: _PetBotCounter(TotalMaxPet),
_FaunaBotCounter(TotalMaxFauna),
_NpcBotCounter(TotalMaxNpc)
{
// _initialised=false;
_TotalBotsSpawned = 0;
_ClientCreatureDebug=false;
}
void setMaxPetCallBack(IVariable &var)
{
uint32 newMax=NLMISC::safe_cast<CVariable<uint32>*>(&var)->get();
if (CAIS::instanceCreated())
CAIS::instance()._PetBotCounter.setMax(newMax);
}
void setMaxFaunaCallBack(IVariable &var)
{
uint32 newMax=NLMISC::safe_cast<CVariable<uint32>*>(&var)->get();
if (CAIS::instanceCreated())
CAIS::instance()._FaunaBotCounter.setMax(newMax);
}
void setMaxNpcCallBack(IVariable &var)
{
uint32 newMax=NLMISC::safe_cast<CVariable<uint32>*>(&var)->get();
if (CAIS::instanceCreated())
CAIS::instance()._NpcBotCounter.setMax(newMax);
}
CVariable<uint32> TotalMaxPlayer("ai", "NbPlayersLimit", "Security absolute limit to the number of Player", Default_MaxPlayers, 0, true );
CVariable<uint32> TotalMaxPet("ai", "NbPetLimit", "Security absolute limit to the number of Pets", Default_MaxBotsPet, 0, true, setMaxPetCallBack );
CVariable<uint32> TotalMaxFauna("ai", "NbFaunaLimit", "Security absolute limit to the number of Faunas", Default_MaxBotsFauna, 0, true, setMaxFaunaCallBack );
CVariable<uint32> TotalMaxNpc("ai", "NbNpcLimit", "Security absolute limit to the number of Npcs", Default_MaxBotsNpc, 0, true, setMaxNpcCallBack );
CVariable<uint32> TotalMaxFx("ai", "NbFxLimit", "Security absolute limit to the number of Fx", Default_MaxBotsFx, 0, true );
CVariable<string> BotRepopFx("ai", "BotRepopFx", "Fx sheet to use when changing the sheet of a bot", string(), 0, true );
//--------------------------------------------------------------------------
// DATA TABLES FOR ENTITY MATRIX
//--------------------------------------------------------------------------
// a series of tables giving the minimum iterator table forms for entity matrix iterators for all sizes up to 127m
static uint32 EntityMatrixTbl0[] = { 3, 3, 3};
static uint32 EntityMatrixTbl16[] = { 3, 5, 5, 5, 3};
static uint32 EntityMatrixTbl23[] = { 5, 5, 5, 5, 5};
static uint32 EntityMatrixTbl32[] = { 3, 5, 7, 7, 7, 5, 3};
static uint32 EntityMatrixTbl36[] = { 5, 7, 7, 7, 7, 7, 5};
static uint32 EntityMatrixTbl46[] = { 7, 7, 7, 7, 7, 7, 7};
static uint32 EntityMatrixTbl48[] = { 3, 7, 7, 9, 9, 9, 7, 7, 3};
static uint32 EntityMatrixTbl51[] = { 5, 7, 9, 9, 9, 9, 9, 7, 5};
static uint32 EntityMatrixTbl58[] = { 7, 9, 9, 9, 9, 9, 9, 9, 7};
static uint32 EntityMatrixTbl64[] = { 3, 7, 9, 9, 11, 11, 11, 9, 9, 7, 3};
static uint32 EntityMatrixTbl66[] = { 5, 7, 9, 11, 11, 11, 11, 11, 9, 7, 5};
static uint32 EntityMatrixTbl68[] = { 5, 9, 9, 11, 11, 11, 11, 11, 9, 9, 5};
static uint32 EntityMatrixTbl72[] = { 7, 9, 11, 11, 11, 11, 11, 11, 11, 9, 7};
static uint32 EntityMatrixTbl80[] = { 3, 9, 11, 11, 11, 13, 13, 13, 11, 11, 11, 9, 3};
static uint32 EntityMatrixTbl82[] = { 5, 9, 11, 11, 13, 13, 13, 13, 13, 11, 11, 9, 5};
static uint32 EntityMatrixTbl87[] = { 7, 9, 11, 13, 13, 13, 13, 13, 13, 13, 11, 9, 7};
static uint32 EntityMatrixTbl91[] = { 7, 11, 11, 13, 13, 13, 13, 13, 13, 13, 11, 11, 7};
static uint32 EntityMatrixTbl94[] = { 9, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 9};
static uint32 EntityMatrixTbl96[] = { 3, 9, 11, 13, 13, 13, 15, 15, 15, 13, 13, 13, 11, 9, 3};
static uint32 EntityMatrixTbl98[] = { 5, 9, 11, 13, 13, 15, 15, 15, 15, 15, 13, 13, 11, 9, 5};
static uint32 EntityMatrixTbl102[] = { 7, 9, 11, 13, 15, 15, 15, 15, 15, 15, 15, 13, 11, 9, 7};
static uint32 EntityMatrixTbl103[] = { 7, 11, 13, 13, 15, 15, 15, 15, 15, 15, 15, 13, 13, 11, 7};
static uint32 EntityMatrixTbl108[] = { 9, 11, 13, 15, 15, 15, 15, 15, 15, 15, 15, 15, 13, 11, 9};
static uint32 EntityMatrixTbl112[] = { 3, 9, 11, 13, 15, 15, 15, 17, 17, 17, 15, 15, 15, 13, 11, 9, 3};
static uint32 EntityMatrixTbl114[] = { 5, 9, 13, 13, 15, 15, 17, 17, 17, 17, 17, 15, 15, 13, 13, 9, 5};
static uint32 EntityMatrixTbl116[] = { 5, 11, 13, 15, 15, 15, 17, 17, 17, 17, 17, 15, 15, 15, 13, 11, 5};
static uint32 EntityMatrixTbl117[] = { 7, 11, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 11, 7};
static uint32 EntityMatrixTbl122[] = { 9, 11, 13, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 15, 13, 11, 9};
static uint32 EntityMatrixTbl125[] = { 9, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 9};
// a few larger special case matrices
static uint32 EntityMatrixTblUpTo150[] = { 7, 11, 15, 17, 17, 19, 19, 21, 21, 21, 21, 21, 21, 21, 19, 19, 17, 17, 15, 11, 7};
static uint32 EntityMatrixTblUpTo200[] = { 9, 13, 17, 19, 21, 23, 23, 25, 25, 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 25, 23, 23, 21, 19, 17, 13, 9};
static uint32 EntityMatrixTblUpTo250[] = {11, 15, 19, 23, 25, 27, 27, 29, 29, 31, 31, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 31, 31, 29, 29, 27, 27, 25, 23, 19, 15, 11};
static void initLinearMatrixIteratorTables(std::vector<CAIEntityMatrixIteratorTblLinear *> &vect)
{
// initialise the vector with the first table
vect.push_back(new CAIEntityMatrixIteratorTblLinear(&(EntityMatrixTbl0[0]),3));
// local macro undefined at end of function
#define ADD_TBL(d) \
{ \
while (vect.size()<d) \
vect.push_back(vect[vect.size()-1]); \
vect.push_back(new CAIEntityMatrixIteratorTblLinear(EntityMatrixTbl##d,sizeof(EntityMatrixTbl##d)/sizeof(EntityMatrixTbl##d[0]))); \
}
// setup the tables ...
ADD_TBL(16) ADD_TBL(23)
ADD_TBL(32) ADD_TBL(36) ADD_TBL(46)
ADD_TBL(48) ADD_TBL(51) ADD_TBL(58)
ADD_TBL(64) ADD_TBL(66) ADD_TBL(68) ADD_TBL(72)
ADD_TBL(80) ADD_TBL(82) ADD_TBL(87) ADD_TBL(91) ADD_TBL(94)
ADD_TBL(96) ADD_TBL(98) ADD_TBL(102) ADD_TBL(103) ADD_TBL(108)
ADD_TBL(112) ADD_TBL(114) ADD_TBL(116) ADD_TBL(117) ADD_TBL(122) ADD_TBL(125)
#undef ADD_TBL
}
bool CAIS::markTagForDelete(const std::string &filename)
{
const TStringId fileId = CStringMapper::map(filename);
for (CCont<CAIInstance>::iterator it=_AIInstances.begin(), itEnd=_AIInstances.end(); it!=itEnd;++it)
{
// first: tag the dynamic regions in the continents
for_each(it->continents().begin(), it->continents().end(),
bind2nd(mem_fun(&CContinent::markTagForDelete), fileId));
for_each(it->managers().begin(),it->managers().end(),
CAliasTreeRoot::CMarkTagForDelete(fileId));
}
return true;
}
void CAIS::deleteTaggedAlias(const std::string &filename)
{
const TStringId fileId = CStringMapper::map(filename);
FOREACH(it, CCont<CAIInstance>, _AIInstances)
{
// first: tag the dynamic regions in the continents
for_each(it->continents().begin(), it->continents().end(),
bind2nd(mem_fun(&CContinent::deleteTaggedAlias),fileId));
for_each(it->managers().begin(),it->managers().end(),
CAliasTreeRoot::CDeleteTagged<CManager>(it->managers()));
}
}
uint32 CAIS::getEmotNumber(const std::string &name)
{
std::map<std::string, uint32>::iterator it(_EmotNames.find(name));
if (it==_EmotNames.end())
return std::numeric_limits<uint32>::max();
return it->second;
}
bool CAIS::advanceUserTimer (uint32 nbTicks)
{
// for each manager, look for a timer event
for_each(AIList().begin(), AIList().end(), bind2nd(mem_fun(&CAIInstance::advanceUserTimer),nbTicks) );
return true;
}
// initialise the singleton
void CAIS::initAI()
{
// if (_initialised)
// return;
// _initialised=true;
nlinfo("---------- Initialising AI Singleton ----------");
// setup the random number generator
_random.srand( (sint32)NLMISC::CTime::getLocalTime() );
// allocate RAM for the players
// setup the standard iterator tables for scanning the entity matrices
_matrixIterator2x2.push_back(-1,-1); _matrixIterator2x2.push_back(1,0);
_matrixIterator2x2.push_back(-1, 1); _matrixIterator2x2.push_back(1,0);
_matrixIterator3x3.push_back(-1,-1); _matrixIterator3x3.push_back(1,0); _matrixIterator3x3.push_back(1,0);
_matrixIterator3x3.push_back(-2, 1); _matrixIterator3x3.push_back(1,0); _matrixIterator3x3.push_back(1,0);
_matrixIterator3x3.push_back(-2, 1); _matrixIterator3x3.push_back(1,0); _matrixIterator3x3.push_back(1,0);
// setup the set of linear iterator tables for generating visions of given distances
initLinearMatrixIteratorTables(_matrixIteratorsByDistance);
EMOTE_LIST_PARSER::initEmoteList(_EmotNames);
// init the client message callbacks
CAIClientMessages::init();
}
uint32 CAIS::createAIInstance(const std::string &continentName, uint32 instanceNumber)
{
// first, check that an instance with this number is not already running
for (CCont<CAIInstance>::iterator it=_AIInstances.begin(), itEnd=_AIInstances.end();it!=itEnd;++it)
{
if (it->getInstanceNumber()!=instanceNumber)
continue;
nlwarning("CAIS::createAIInstance: instance number %u is already in use, can't create new instance.", instanceNumber);
return std::numeric_limits<uint32>::max();
}
CAIInstance *aii = _AIInstances.addChild(new CAIInstance(this));
// ok, set the continent name and instance number
aii->initInstance(continentName, instanceNumber);
return aii->getChildIndex();
}
void CAIS::destroyAIInstance(uint32 instanceNumber, bool displayWarningIfInstanceNotExist)
{
// this method is not fully tested for a Ryzom shard
// but it should work as expected for a Ring shard
nlassert(IsRingShard.get());
CRefPtr<CAIInstance> aii = getAIInstance(instanceNumber);
if (aii == NULL)
{
if (displayWarningIfInstanceNotExist)
{
nlwarning("AI instance %u does not exist but it was asked to delete here", instanceNumber);
}
return;
}
aii->despawn();
_AIInstances.removeChildByIndex(aii->getChildIndex());
nlassert(aii == NULL);
// notify the EGS
if (EGSHasMirrorReady)
{
CReportAIInstanceDespawnMsg msg;
msg.InstanceNumbers.push_back(instanceNumber);
msg.send("EGS");
}
}
// release the singleton before program exit
void CAIS::release ()
{
// force an update to save the persistent var if needed
updatePersistentVariables();
// erase all ai instance.
AIList().clear();
CAIUserModelManager::getInstance()->destroyInstance();
// release the client message callbacks
CAIClientMessages::release();
// free up the vision matrix iterator tables
if (!_matrixIteratorsByDistance.empty())
{
for (uint i=0;i<_matrixIteratorsByDistance.size();)
{
// erase the iterator table
delete _matrixIteratorsByDistance[i];
// run i forwards past repeated refs to the iterator tbl that we just deleted
for (++i;i<_matrixIteratorsByDistance.size() && _matrixIteratorsByDistance[i]==_matrixIteratorsByDistance[i-1];++i) {}
}
_matrixIteratorsByDistance.clear();
}
_Instance = NULL;
delete this;
}
void CAIS::serviceEvent (const CServiceEvent &info)
{
if (info.getEventType() == CServiceEvent::SERVICE_UP && info.getServiceName() == "EGS")
{
// send the list of available collision data
CReportAICollisionAvailableMsg msg;
msg.ContinentsCollision = CWorldContainer::getContinentList();
msg.send(info.getServiceId());
}
// event on all ai instance
// for_each(_AIInstances.begin(), _AIInstances.end(), bind2nd(mem_fun1(&CAIInstance::serviceEvent), info));
// don't compile coz we need to pass an object and not a reference (info). have to build an object that represents the reference.
FOREACH(it, CCont<CAIInstance>, _AIInstances)
it->serviceEvent (info);
}
//--------------------------------------------------------------------------
// update() & save()
//--------------------------------------------------------------------------
// the update routine called once per tick
// this is the routine that calls the managers' updates
extern void execBufferedCommands();
extern void execNamedEntityChanges();
void CAIS::update()
{
if (!EGSHasMirrorReady)
return;
H_AUTO(AIUpdate);
// Init stat counters
AISStat::countersBegin();
// Execute buffered Task
uint32 tick = CTimeInterface::gameCycle();
_TickedTaskList.execute(tick);
// Execute buffered functions that need to be executed in the correct context
execBufferedCommands();
execNamedEntityChanges();
// Update AI instances
FOREACH(it, CCont<CAIInstance>, CAIS::instance().AIList())
(*it)->CAIInstance::update();
// Send systematic messages to EGS
if (EGSHasMirrorReady)
{
// send the fauna description message to EGS then clear the content.
if (!_FaunaDescriptionList.Bots.empty())
{
nlassert(_FaunaDescriptionList.Bots.size() == _FaunaDescriptionList.GrpAlias.size());
_FaunaDescriptionList.send("EGS");
_FaunaDescriptionList.Bots.clear();
_FaunaDescriptionList.GrpAlias.clear();
}
// send agglomerated hp changes
if (!_CreatureChangeHPList.Entities.empty())
{
nlassert(_CreatureChangeHPList.Entities.size()==_CreatureChangeHPList.DeltaHp.size());
_CreatureChangeHPList.send("EGS");
_CreatureChangeHPList.Entities.clear();
_CreatureChangeHPList.DeltaHp.clear();
}
if (!_CreatureChangeMaxHPList.Entities.empty())
{
nlassert(_CreatureChangeMaxHPList.Entities.size()==_CreatureChangeMaxHPList.MaxHp.size());
nlassert(_CreatureChangeMaxHPList.Entities.size()==_CreatureChangeMaxHPList.SetFull.size());
_CreatureChangeMaxHPList.send("EGS");
_CreatureChangeMaxHPList.Entities.clear();
_CreatureChangeMaxHPList.MaxHp.clear();
_CreatureChangeMaxHPList.SetFull.clear();
}
}
//
// update persistent variables every 1024 tick if AI script data manager is flagged
if ((tick & 0x3FF) == 0)
{
updatePersistentVariables();
}
//TODO: UserModelManager must send UserModels to EGS if not done yet
//CAIUserModelManager::getInstance()->sendUserModels();
// Terminate counters and store stats in an accessible place
AISStat::countersEnd();
}
// provoke a general 'save to backup' across the whole service
void CAIS::save()
{
nlinfo("*** save() NOT IMPLEMENTED YET ***");
}
//--------------------------------------------------------------------------
// management of iterator tables for vision matrices
//--------------------------------------------------------------------------
const CAIEntityMatrixIteratorTblLinear* CAIS::bestLinearMatrixIteratorTbl(uint32 distInMeters)
{
#if !FINAL_VERSION
nlassert(!_matrixIteratorsByDistance.empty());
#endif
if (distInMeters >= _matrixIteratorsByDistance.size())
{
//nlwarning("Try to access to a Vision Matrix to far %u the farest is only %u", distInMeters, _matrixIteratorsByDistance.size());
return _matrixIteratorsByDistance.back();
}
return _matrixIteratorsByDistance[distInMeters];
}
int getInt64FromStr (const char* str)
{
if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
return (int) atoiInt64(str+2,16);
return (int) atoiInt64(str,10);
}
// all these dynamics casts can be throwned away ..
CAIInstance* CAIS::tryToGetAIInstance(const char* str)
{
return dynamic_cast<CAIInstance*> (tryToGetEntity(str,CAIS::AI_INSTANCE));
}
CContinent *CAIS::tryToGetContinent (const char *str)
{
return dynamic_cast<CContinent*> (tryToGetEntity(str,CAIS::AI_CONTINENT));
}
CRegion *CAIS::tryToGetRegion (const char *str)
{
return dynamic_cast<CRegion*> (tryToGetEntity(str,CAIS::AI_REGION));
}
CCellZone *CAIS::tryToGetCellZone (const char *str)
{
return dynamic_cast<CCellZone*> (tryToGetEntity(str,CAIS::AI_CELL_ZONE));
}
CFamilyBehavior *CAIS::tryToGetFamilyBehavior (const char *str)
{
return dynamic_cast<CFamilyBehavior*> (tryToGetEntity(str,CAIS::AI_FAMILY_BEHAVIOR));
}
CManager* CAIS::tryToGetManager(const char* str)
{
return dynamic_cast<CManager*> (tryToGetEntity(str,CAIS::AI_MANAGER));
}
CGroup* CAIS::tryToGetGroup(const char* str)
{
return dynamic_cast<CGroup*> (tryToGetEntity(str,CAIS::AI_GROUP));
}
CBot* CAIS::tryToGetBot(const char* str)
{
return dynamic_cast<CBot*> (tryToGetEntity(str,CAIS::AI_BOT));
}
CAIEntity* CAIS::tryToGetAIEntity(const char* str)
{
return dynamic_cast<CAIEntity*> (tryToGetEntity(str));
}
CAIEntityPhysical* CAIS::tryToGetEntityPhysical(const char* str)
{
CEntityId entityId;
entityId.fromString(str);
return CAIS::getEntityPhysical(CMirrors::DataSet->getDataSetRow(entityId));
}
CAIEntity* CAIS::tryToGetEntity(const char* str, TSearchType searchType)
{
CAIInstance *aii = NULL;
CManager *mgr = NULL;
CBot *bot = NULL;
CGroup *grp = NULL;
vector<string> parts;
explode(string(str), string(":"), parts, false);
if (parts.empty() || parts[0].empty())
return NULL;
// skip AIS number if any
if (parts[0].substr(0, 4) == "AIS_")
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// instance index
uint32 index = atoui(parts[0].c_str());
if (index >= CAIS::instance().AIList().size())
goto tryWithEntityId;
aii = CAIS::AIList()[index];
if (!aii)
goto tryWithEntityId;
if (searchType==CAIS::AI_INSTANCE
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return aii;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// branch on static or dynamic system
// manager index
if (parts[0].find("dyn_") == 0)
{
// parse dynamic id
// continent index
index = atoui(parts[0].substr(4).c_str());
if (index >= aii->continents().size())
return NULL;
CContinent *continent = aii->continents()[index];
if (searchType==CAIS::AI_CONTINENT
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return continent;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// region index
index = atoui(parts[0].c_str());
if (index >= continent->regions().size())
return NULL;
CRegion *region = continent->regions()[index];
if (searchType==CAIS::AI_REGION
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return region;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// cellzone index
index = atoui(parts[0].c_str());
if (index >= region->cellZones().size())
return NULL;
CCellZone *cz = region->cellZones()[index];
if (searchType==CAIS::AI_CELL_ZONE
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return cz;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// family behavior index
index = atoui(parts[0].c_str());
if (index >= cz->familyBehaviors().size())
return NULL;
CFamilyBehavior *fb = cz->familyBehaviors()[index];
if (searchType==CAIS::AI_FAMILY_BEHAVIOR
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return fb;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty())
return NULL;
// manager index
if (parts[0] == "npc")
mgr = fb->mgrNpc();
else if (parts[0] == "fauna")
mgr = fb->mgrFauna();
if (!mgr)
return NULL;
if (searchType==CAIS::AI_MANAGER
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1)
|| mgr == NULL)
return mgr;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
}
else
{
// parse static id
// Manager index
index = atoui(parts[0].c_str());
if (index >= aii->managers().size())
return NULL;
mgr = aii->managers()[index];
if (searchType==CAIS::AI_MANAGER
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1)
|| mgr == NULL)
return mgr;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
}
// group index
index = atoui(parts[0].c_str());
if (index >= mgr->groups().size())
return NULL;
grp = mgr->groups()[index];
if (searchType==CAIS::AI_GROUP
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return grp;
parts.erase(parts.begin());
// check
if (parts.empty() || parts[0].empty()) return NULL;
// bot index
index = atoui(parts[0].c_str());
if (index >= grp->bots().size())
return NULL;
bot = grp->bots()[index];
if (searchType==CAIS::AI_BOT
|| (searchType == CAIS::AI_UNDEFINED && parts.size() == 1))
return bot;
// what ?
return NULL;
tryWithEntityId:
CEntityId entityId;
entityId.fromString(str);
if (entityId.isUnknownId())
return NULL;
CCont<CAIInstance>::iterator instanceIt=CAIS::instance().AIList().begin(), instanceItEnd=CAIS::instance().AIList().end();
while (instanceIt!=instanceItEnd)
{
CAIInstance *instancePtr=*instanceIt;
CCont<CManager>::iterator it=instancePtr->managers().begin(), itEnd=instancePtr->managers().end();
while (it!=itEnd)
{
CManager *mgrPtr = *it;
CGroup *grpPtr = mgrPtr->getNextValidGroupChild ();
while (grpPtr)
{
CBot *botPtr = grpPtr->getNextValidBotChild();
while (botPtr)
{
if ( botPtr->isSpawned()
&& botPtr->getSpawnObj()->getEntityId() == entityId)
return dynamic_cast<CAIEntity*> (botPtr);
botPtr = grpPtr->getNextValidBotChild (botPtr);
}
grpPtr=mgrPtr->getNextValidGroupChild (grpPtr);
}
++it;
}
++instanceIt;
}
return NULL;
}
//--------------------------------------------------------------------------
// manageing the set of maps
//--------------------------------------------------------------------------
CAIEntityPhysical *CAIS::getEntityPhysical(const TDataSetRow& row)
{
CHashMap<int,NLMISC::CDbgPtr<CAIEntityPhysical> >::iterator it(_CAIEntityByDataSetRow.find(row.getIndex()));
if (it!=_CAIEntityByDataSetRow.end())
return (*it).second;
else
return NULL;
// the code below generates an error .. :( hu !
}
//-------------------------------------------------------------------
// Interface to bot chat - callbacks called when bots start or
// stop chatting with player(s)
//-------------------------------------------------------------------
void CAIS::beginBotChat(const TDataSetRow &bot,const TDataSetRow &player)
{
#ifdef NL_DEBUG
/// Is this still true?
nlwarning("Chat can't work now as bot are now splitted in persistent and spawnable part. Have to rework on this part.");
#endif
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::beginBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// get a pointer to the player
CBotPlayer* plrPtr = dynamic_cast<CBotPlayer*>(CAIS::getEntityPhysical(player));
if (plrPtr==NULL)
{
// nlwarning("CAIS::beginBotChat(): Bot chat message identifies an unknown player!!!");
return;
}
// have the bot register the chat
botNpc->beginBotChat(plrPtr);
}
void CAIS::endBotChat(const TDataSetRow &bot, const TDataSetRow &player)
{
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::endBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// get a pointer to the player
CBotPlayer* plrPtr = dynamic_cast<CBotPlayer*>(CAIS::getEntityPhysical(player));
if (!plrPtr)
{
// nlwarning("CAIS::endBotChat(): Bot chat message identifies an unknown player!!!");
return;
}
// have the bot register the chat end
botNpc->endBotChat(plrPtr);
}
void CAIS::beginDynChat(const TDataSetRow &bot)
{
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::beginBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// have the bot register the chat
botNpc->beginDynChat();
nldebug( "DYNCHT: E%u: %u dyn chats", bot.getIndex(), botNpc->getNbActiveDynChats() );
}
void CAIS::endDynChat(const TDataSetRow &bot)
{
// get a pointer to the bot
CSpawnBotNpc* botNpc=dynamic_cast<CSpawnBotNpc*>(CAIS::getEntityPhysical(bot));
if (!botNpc)
{
// nlwarning("CAIS::endBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
return;
}
// have the bot register the chat end
botNpc->endDynChat();
nldebug( "DYNCHT: E%u: %u dyn chats", bot.getIndex(), botNpc->getNbActiveDynChats() );
}
void CAIPlaceXYR::display(CStringWriter &stringWriter) const
{
stringWriter.append("XYR: ("+_pos.x().toString()
+" "
+_pos.y().toString()
+" "+toString(_pos.h())
+") Radius "
+toString(_radius)
+" "
+getName());
// nlinfo("XYR: (%s,%s,%d) x %f :%s",_pos.x().toString().c_str(),_pos.y().toString().c_str(),_pos.h(),_radius,getName().c_str());
}
void CAIS::warnBadInstanceMsgImp(const std::string &serviceName, TServiceId serviceId, CWarnBadInstanceMsgImp &msg)
{
// EGS says that an instance is spoofing an instance number or using a bad static instance number/continent name association.
// we must despawn/delete the aiinstance
FOREACH(it, CCont<CAIInstance>, _AIInstances)
{
if ((*it)->getInstanceNumber()!=msg.InstanceNumber)
continue;
// ok, we found the bad guy !
nlwarning("CAIS::warnBadInstanceMsgImp: despawning AIInstance %u, instance number %u, continent '%s'",
(*it)->getChildIndex(), msg.InstanceNumber, (*it)->getContinentName().c_str());
_AIInstances.removeChildByIndex((*it)->getChildIndex());
return;
}
// not found
nlwarning("CAIS::warnBadInstanceMsgImp: can't find AIInstance with instance number %u ! Can't despawn it", msg.InstanceNumber);
}
void CAIS::updatePersistentVariables()
{
if (CAIScriptDataManager::getInstance()->needsPersistentVarUpdate() == true)
{
// sending data to bs
CPersistentDataRecord pdr("AiTokenFamily");
CAIScriptDataManager::getInstance()->getPersistentVariables().store(pdr);
uint32 bufSize= pdr.totalDataSize();
vector<char> buffer;
buffer.resize(bufSize);
pdr.toBuffer(&buffer[0],bufSize);
CBackupMsgSaveFile msg( CAIScriptDataManager::getInstance()->makePdrFileName(), CBackupMsgSaveFile::SaveFile, Bsi );
msg.DataMsg.serialBuffer((uint8*)&buffer[0], bufSize);
Bsi.sendFile( msg );
CAIScriptDataManager::getInstance()->clearDirtyFlag();
}
}
CAIInstance *CAIS::getAIInstance(uint32 instanceNumber)
{
FOREACH(it, CCont<CAIInstance>, _AIInstances)
{
if ((*it)->getInstanceNumber()==instanceNumber)
return *it;
}
return NULL;
}

View file

@ -1,189 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "magic_action.h"
#include "magic_phrase.h"
#include "creature.h"
#include "character.h"
#include "phrase_utilities_functions.h"
#include "game_share/entity_structure/statistic.h"
#include "game_share/magic_fx.h"
#include "s_link_effect_hot.h"
using namespace NLNET;
using namespace NLMISC;
using namespace RY_GAME_SHARE;
using namespace std;
class CMagicActionHot : public IMagicAction
{
public:
CMagicActionHot()
<<<<<<< HEAD
:_HealChaScore1(0),_HealChaScore3(0),_HealChaScore2(0),_CostPerUpdate(0),_Power(0){}
=======
:_HealHp(0),_HealSap(0),_HealSta(0),_CostPerUpdate(0),_Power(0){}
>>>>>>> ryzomcore
protected:
virtual bool addBrick( const CStaticBrick & brick, CMagicPhrase * phrase, bool &effectEnd )
{
for ( uint i=0 ; i<brick.Params.size() ; ++i)
{
switch(brick.Params[i]->id())
{
case TBrickParam::MA_END:
INFOLOG("MA_END Found: end of effect");
effectEnd = true;
return true;
case TBrickParam::MA_HEAL:
<<<<<<< HEAD
INFOLOG("MA_HEAL: %u %u %u",((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore1,((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore3,((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore2);
_HealChaScore1 = ((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore1;
_HealChaScore3 = ((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore3;
_HealChaScore2 = ((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore2;
=======
INFOLOG("MA_HEAL: %u %u %u",((CSBrickParamMagicHeal *)brick.Params[i])->Hp,((CSBrickParamMagicHeal *)brick.Params[i])->Sap,((CSBrickParamMagicHeal *)brick.Params[i])->Sta);
_HealHp = ((CSBrickParamMagicHeal *)brick.Params[i])->Hp;
_HealSap = ((CSBrickParamMagicHeal *)brick.Params[i])->Sap;
_HealSta = ((CSBrickParamMagicHeal *)brick.Params[i])->Sta;
>>>>>>> ryzomcore
case TBrickParam::MA_LINK_COST:
INFOLOG("MA_LINK_COST: %u",((CSBrickParamMagicLinkCost *)brick.Params[i])->Cost);
_CostPerUpdate = ((CSBrickParamMagicLinkCost *)brick.Params[i])->Cost;
break;
case TBrickParam::MA_LINK_POWER:
INFOLOG("MA_LINK_POWER: %u",((CSBrickParamMagicLinkPower *)brick.Params[i])->Power);
_Power = (uint8) ( ((CSBrickParamMagicLinkPower *)brick.Params[i])->Power );
break;
default:
// unused param, can be useful in the phrase
phrase->applyBrickParam( brick.Params[i] );
break;
}
}
///\todo nico: check if everything is set
return true;
}
virtual bool validate(CMagicPhrase * phrase)
{
return PHRASE_UTILITIES::validateSpellTarget(phrase->getActor(),phrase->getTargets()[0],ACTNATURE::DEFENSIVE);
}
virtual void apply( CMagicPhrase * phrase, float successFactor,MBEHAV::CBehaviour & behav , bool isMad )
{
// behav.Spell.Resist = 0;
//behav.Spell.KillingBlow = 0;
behav.Spell.SpellIntensity = 5;
CEntityBase* actor = CEntityBaseManager::getEntityBasePtr( phrase->getActor() );
if (!actor)
return;
if ( successFactor <= 0.0f )
{
if ( actor->getId().getType() == RYZOMID::player )
CCharacter::sendMessageToClient( actor->getId(),"MAGIC_TOTAL_MISS" );
}
/// apply success factor
const std::vector< TDataSetRow > & targets = phrase->getTargets();
SCORES::TScores linkEnergy;
<<<<<<< HEAD
if ( phrase->getChaScore1Cost() > 0 )
{
linkEnergy = SCORES::cha_score1;
}
else
linkEnergy = SCORES::cha_score3;
=======
if ( phrase->getHPCost() > 0 )
{
linkEnergy = SCORES::hit_points;
}
else
linkEnergy = SCORES::sap;
>>>>>>> ryzomcore
for ( uint i = 0; i < targets.size(); i++ )
{
// check target
CEntityBase* target = CEntityBaseManager::getEntityBasePtr( targets[i] );
if ( !target)
continue;
/// someone can only have 1 effect of a given type on a creature
const std::vector< CSEffect* > & effects = target->getSEffects();
for (uint j = 0; j < effects.size(); j++ )
{
if ( effects[j]->getFamily() == EFFECT_FAMILIES::Hot && effects[j]->getCreatorRowId() == phrase->getActor( ) )
{
return;
}
}
if ( isMad || PHRASE_UTILITIES::validateSpellTarget(actor->getEntityRowId(),target->getEntityRowId(),ACTNATURE::DEFENSIVE) )
{
CSLinkEffectHot* hot = new CSLinkEffectHot( phrase->getActor(),
targets[i],
_CostPerUpdate,
linkEnergy,
_Skill,
_Power,
<<<<<<< HEAD
uint32(_HealChaScore1 * successFactor* CSLinkEffect::getUpdatePeriod()),
uint32(_HealChaScore3 * successFactor* CSLinkEffect::getUpdatePeriod()),
uint32(_HealChaScore2 * successFactor* CSLinkEffect::getUpdatePeriod()) );
=======
uint32(_HealHp * successFactor* CSLinkEffect::getUpdatePeriod()),
uint32(_HealSap * successFactor* CSLinkEffect::getUpdatePeriod()),
uint32(_HealSta * successFactor* CSLinkEffect::getUpdatePeriod()) );
>>>>>>> ryzomcore
actor->addLink( hot );
target->addSabrinaEffect( hot );
<<<<<<< HEAD
behav.Spell.SpellId = MAGICFX::healtoMagicFx( _HealChaScore1,_HealChaScore3,_HealChaScore2,true );
}
}
}
sint32 _HealChaScore1;
sint32 _HealChaScore3;
sint32 _HealChaScore2;
=======
behav.Spell.SpellId = MAGICFX::healtoMagicFx( _HealHp,_HealSap,_HealSta,true );
}
}
}
sint32 _HealHp;
sint32 _HealSap;
sint32 _HealSta;
>>>>>>> ryzomcore
uint _CostPerUpdate;
uint8 _Power;
};
BEGIN_MAGIC_ACTION_FACTORY(CMagicActionHot)
ADD_MAGIC_ACTION_TYPE( "mlc" )
END_MAGIC_ACTION_FACTORY(CMagicActionHot)

View file

@ -1,153 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "magic_action.h"
#include "magic_phrase.h"
#include "creature.h"
#include "character.h"
#include "phrase_utilities_functions.h"
#include "game_share/entity_structure/statistic.h"
#include "game_share/magic_fx.h"
#include "s_link_effect_hot.h"
using namespace NLNET;
using namespace NLMISC;
using namespace RY_GAME_SHARE;
using namespace std;
class CMagicActionHot : public IMagicAction
{
public:
CMagicActionHot()
:_HealChaScore1(0),_HealChaScore3(0),_HealChaScore2(0),_CostPerUpdate(0),_Power(0){}
protected:
virtual bool addBrick( const CStaticBrick & brick, CMagicPhrase * phrase, bool &effectEnd )
{
for ( uint i=0 ; i<brick.Params.size() ; ++i)
{
switch(brick.Params[i]->id())
{
case TBrickParam::MA_END:
INFOLOG("MA_END Found: end of effect");
effectEnd = true;
return true;
case TBrickParam::MA_HEAL:
INFOLOG("MA_HEAL: %u %u %u",((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore1,((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore3,((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore2);
_HealChaScore1 = ((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore1;
_HealChaScore3 = ((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore3;
_HealChaScore2 = ((CSBrickParamMagicHeal *)brick.Params[i])->ChaScore2;
case TBrickParam::MA_LINK_COST:
INFOLOG("MA_LINK_COST: %u",((CSBrickParamMagicLinkCost *)brick.Params[i])->Cost);
_CostPerUpdate = ((CSBrickParamMagicLinkCost *)brick.Params[i])->Cost;
break;
case TBrickParam::MA_LINK_POWER:
INFOLOG("MA_LINK_POWER: %u",((CSBrickParamMagicLinkPower *)brick.Params[i])->Power);
_Power = (uint8) ( ((CSBrickParamMagicLinkPower *)brick.Params[i])->Power );
break;
default:
// unused param, can be useful in the phrase
phrase->applyBrickParam( brick.Params[i] );
break;
}
}
///\todo nico: check if everything is set
return true;
}
virtual bool validate(CMagicPhrase * phrase)
{
return PHRASE_UTILITIES::validateSpellTarget(phrase->getActor(),phrase->getTargets()[0],ACTNATURE::DEFENSIVE);
}
virtual void apply( CMagicPhrase * phrase, float successFactor,MBEHAV::CBehaviour & behav , bool isMad )
{
// behav.Spell.Resist = 0;
//behav.Spell.KillingBlow = 0;
behav.Spell.SpellIntensity = 5;
CEntityBase* actor = CEntityBaseManager::getEntityBasePtr( phrase->getActor() );
if (!actor)
return;
if ( successFactor <= 0.0f )
{
if ( actor->getId().getType() == RYZOMID::player )
CCharacter::sendMessageToClient( actor->getId(),"MAGIC_TOTAL_MISS" );
}
/// apply success factor
const std::vector< TDataSetRow > & targets = phrase->getTargets();
SCORES::TScores linkEnergy;
if ( phrase->getChaScore1Cost() > 0 )
{
linkEnergy = SCORES::cha_score1;
}
else
linkEnergy = SCORES::cha_score3;
for ( uint i = 0; i < targets.size(); i++ )
{
// check target
CEntityBase* target = CEntityBaseManager::getEntityBasePtr( targets[i] );
if ( !target)
continue;
/// someone can only have 1 effect of a given type on a creature
const std::vector< CSEffect* > & effects = target->getSEffects();
for (uint j = 0; j < effects.size(); j++ )
{
if ( effects[j]->getFamily() == EFFECT_FAMILIES::Hot && effects[j]->getCreatorRowId() == phrase->getActor( ) )
{
return;
}
}
if ( isMad || PHRASE_UTILITIES::validateSpellTarget(actor->getEntityRowId(),target->getEntityRowId(),ACTNATURE::DEFENSIVE) )
{
CSLinkEffectHot* hot = new CSLinkEffectHot( phrase->getActor(),
targets[i],
_CostPerUpdate,
linkEnergy,
_Skill,
_Power,
uint32(_HealChaScore1 * successFactor* CSLinkEffect::getUpdatePeriod()),
uint32(_HealChaScore3 * successFactor* CSLinkEffect::getUpdatePeriod()),
uint32(_HealChaScore2 * successFactor* CSLinkEffect::getUpdatePeriod()) );
actor->addLink( hot );
target->addSabrinaEffect( hot );
behav.Spell.SpellId = MAGICFX::healtoMagicFx( _HealChaScore1,_HealChaScore3,_HealChaScore2,true );
}
}
}
sint32 _HealChaScore1;
sint32 _HealChaScore3;
sint32 _HealChaScore2;
uint _CostPerUpdate;
uint8 _Power;
};
BEGIN_MAGIC_ACTION_FACTORY(CMagicActionHot)
ADD_MAGIC_ACTION_TYPE( "mlc" )
END_MAGIC_ACTION_FACTORY(CMagicActionHot)

View file

@ -1,153 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "magic_action.h"
#include "magic_phrase.h"
#include "creature.h"
#include "character.h"
#include "phrase_utilities_functions.h"
#include "game_share/entity_structure/statistic.h"
#include "game_share/magic_fx.h"
#include "s_link_effect_hot.h"
using namespace NLNET;
using namespace NLMISC;
using namespace RY_GAME_SHARE;
using namespace std;
class CMagicActionHot : public IMagicAction
{
public:
CMagicActionHot()
:_HealHp(0),_HealSap(0),_HealSta(0),_CostPerUpdate(0),_Power(0){}
protected:
virtual bool addBrick( const CStaticBrick & brick, CMagicPhrase * phrase, bool &effectEnd )
{
for ( uint i=0 ; i<brick.Params.size() ; ++i)
{
switch(brick.Params[i]->id())
{
case TBrickParam::MA_END:
INFOLOG("MA_END Found: end of effect");
effectEnd = true;
return true;
case TBrickParam::MA_HEAL:
INFOLOG("MA_HEAL: %u %u %u",((CSBrickParamMagicHeal *)brick.Params[i])->Hp,((CSBrickParamMagicHeal *)brick.Params[i])->Sap,((CSBrickParamMagicHeal *)brick.Params[i])->Sta);
_HealHp = ((CSBrickParamMagicHeal *)brick.Params[i])->Hp;
_HealSap = ((CSBrickParamMagicHeal *)brick.Params[i])->Sap;
_HealSta = ((CSBrickParamMagicHeal *)brick.Params[i])->Sta;
case TBrickParam::MA_LINK_COST:
INFOLOG("MA_LINK_COST: %u",((CSBrickParamMagicLinkCost *)brick.Params[i])->Cost);
_CostPerUpdate = ((CSBrickParamMagicLinkCost *)brick.Params[i])->Cost;
break;
case TBrickParam::MA_LINK_POWER:
INFOLOG("MA_LINK_POWER: %u",((CSBrickParamMagicLinkPower *)brick.Params[i])->Power);
_Power = (uint8) ( ((CSBrickParamMagicLinkPower *)brick.Params[i])->Power );
break;
default:
// unused param, can be useful in the phrase
phrase->applyBrickParam( brick.Params[i] );
break;
}
}
///\todo nico: check if everything is set
return true;
}
virtual bool validate(CMagicPhrase * phrase)
{
return PHRASE_UTILITIES::validateSpellTarget(phrase->getActor(),phrase->getTargets()[0],ACTNATURE::DEFENSIVE);
}
virtual void apply( CMagicPhrase * phrase, float successFactor,MBEHAV::CBehaviour & behav , bool isMad )
{
// behav.Spell.Resist = 0;
//behav.Spell.KillingBlow = 0;
behav.Spell.SpellIntensity = 5;
CEntityBase* actor = CEntityBaseManager::getEntityBasePtr( phrase->getActor() );
if (!actor)
return;
if ( successFactor <= 0.0f )
{
if ( actor->getId().getType() == RYZOMID::player )
CCharacter::sendMessageToClient( actor->getId(),"MAGIC_TOTAL_MISS" );
}
/// apply success factor
const std::vector< TDataSetRow > & targets = phrase->getTargets();
SCORES::TScores linkEnergy;
if ( phrase->getHPCost() > 0 )
{
linkEnergy = SCORES::hit_points;
}
else
linkEnergy = SCORES::sap;
for ( uint i = 0; i < targets.size(); i++ )
{
// check target
CEntityBase* target = CEntityBaseManager::getEntityBasePtr( targets[i] );
if ( !target)
continue;
/// someone can only have 1 effect of a given type on a creature
const std::vector< CSEffect* > & effects = target->getSEffects();
for (uint j = 0; j < effects.size(); j++ )
{
if ( effects[j]->getFamily() == EFFECT_FAMILIES::Hot && effects[j]->getCreatorRowId() == phrase->getActor( ) )
{
return;
}
}
if ( isMad || PHRASE_UTILITIES::validateSpellTarget(actor->getEntityRowId(),target->getEntityRowId(),ACTNATURE::DEFENSIVE) )
{
CSLinkEffectHot* hot = new CSLinkEffectHot( phrase->getActor(),
targets[i],
_CostPerUpdate,
linkEnergy,
_Skill,
_Power,
uint32(_HealHp * successFactor* CSLinkEffect::getUpdatePeriod()),
uint32(_HealSap * successFactor* CSLinkEffect::getUpdatePeriod()),
uint32(_HealSta * successFactor* CSLinkEffect::getUpdatePeriod()) );
actor->addLink( hot );
target->addSabrinaEffect( hot );
behav.Spell.SpellId = MAGICFX::healtoMagicFx( _HealHp,_HealSap,_HealSta,true );
}
}
}
sint32 _HealHp;
sint32 _HealSap;
sint32 _HealSta;
uint _CostPerUpdate;
uint8 _Power;
};
BEGIN_MAGIC_ACTION_FACTORY(CMagicActionHot)
ADD_MAGIC_ACTION_TYPE( "mlc" )
END_MAGIC_ACTION_FACTORY(CMagicActionHot)