Fixes
[ryzomcore.git] / ryzom / client / data / gamedev / interfaces_v3 / player.lua
blob6efbc1a6fe743d9d0a5b4341ca20d80bb8e83786
1 -- In this file we define functions that serves for player windows
3 function getDbPropU(dbEntry)
4 value = getDbProp(dbEntry)
5 if (value < 0) then
6 value = 4294967296+value
7 end
8 return value
9 end
11 if string.find(_VERSION, "Lua 5.0") then
12 function math.fmod(a, b)
13 return math.mod(a, b)
14 end
15 end
17 ------------------------------------------------------------------------------------------------------------
18 -- create the game namespace without reseting if already created in an other file.
19 if (game==nil) then
20 game= {};
21 end
23 if (game.PVP == nil) then
24 game.PVP = {};
25 game.PVP.tagStartTimer = 0;
26 game.PVP.flagStartTimer = 0;
27 game.PVP.tagTimerStarted = false;
28 game.PVP.flagTimerStarted = false;
29 end
31 if (game.BonusMalus == nil) then
32 game.BonusMalus = {};
33 game.BonusMalus.DeathPenaltyBefore = -1;
34 game.BonusMalus.DeathPenaltyAfter = -1;
35 game.BonusMalus.XPCatSlotBefore = -1;
36 game.BonusMalus.XPCatSlotAfter = -1;
37 game.BonusMalus.RingXPCatSlotBefore = -1;
38 game.BonusMalus.RingXPCatSlotAfter = -1;
39 game.BonusMalus.OutpostSlotBefore = -1;
40 game.BonusMalus.OutpostSlotAfter = -1;
41 game.BonusMalus.BonusAHList= {};
42 game.BonusMalus.MalusAHList= {};
43 end
45 game.wantedScriptPlaces = {}
46 game.latestValidScriptPlace = ""
48 function game:addScriptPlace(modname, place, id)
49 if game.wantedScriptPlaces[modname] == nil then
50 game.wantedScriptPlaces[modname] = {}
51 end
52 game.wantedScriptPlaces[modname][place] = id
53 end
56 function game:checkScriptPlace(place)
57 for modname, vals in pairs(game.wantedScriptPlaces) do
58 if vals[place] ~= nil and game.latestValidScriptPlace ~= place then
59 game.latestValidScriptPlace = place
60 openArkScript(vals[place], nil, "place="..place)
61 end
62 end
63 end
66 function game:CheckPosition()
67 local x,y,z = getPlayerPos()
68 local sx = tostring(math.floor(x/10))
69 local sy = tostring(math.floor(y/10))
70 game:checkRpItemsPosition(sx, sy)
71 local cont, region, places = getPositionInfos()
72 game:checkScriptPlace(cont)
73 game:checkScriptPlace(region)
74 for place, typ in pairs(places) do
75 game:checkScriptPlace(place)
76 end
77 end
79 ------------------------------------------------------------------------------------------------------------
80 -- Update player bars in function of what we wants to display (we can hide each one of the 3 bars : sap,stamina and focus)
81 function game:updatePlayerBars()
83 local dispSap = getDbProp('UI:SAVE:PLAYER:DISP_SAP');
84 local dispSta = getDbProp('UI:SAVE:PLAYER:DISP_STA');
85 local dispFoc = getDbProp('UI:SAVE:PLAYER:DISP_FOC');
87 local ui = getUI('ui:interface:player:content');
89 -- active ui in function of what is displayed
91 ui.b_sap.active = (dispSap == 1);
92 ui.jsap.active = (dispSap == 1);
94 ui.b_sta.active = (dispSta == 1);
95 ui.jsta.active = (dispSta == 1);
97 ui.b_foc.active = (dispFoc == 1);
98 ui.jfoc.active = (dispFoc == 1);
100 -- choose good y-position
102 local totalBarDisp = dispSap + dispSta + dispFoc;
103 if (totalBarDisp == 3) then
105 ui.b_sap.y = -20;
106 ui.b_sta.y = -35;
107 ui.b_foc.y = -50;
108 ui.current_action.y = -65;
110 elseif (totalBarDisp == 2) then
112 if (dispSap == 0) then
113 ui.b_sta.y = -20;
114 ui.b_foc.y = -35;
117 if (dispSta == 0) then
118 ui.b_sap.y = -20;
119 ui.b_foc.y = -35;
122 if (dispFoc == 0) then
123 ui.b_sap.y = -20;
124 ui.b_sta.y = -35;
127 ui.current_action.y = -50;
129 elseif (totalBarDisp == 1) then
131 ui.b_sta.y = -20;
132 ui.b_foc.y = -20;
133 ui.b_sta.y = -20;
135 ui.current_action.y = -35;
137 else
138 ui.current_action.y = -20;
145 ------------------------------------------------------------------------------------------------------------
146 -- convert a boolean to a number 0 or 1
147 function booleanToNumber(thebool)
148 if(thebool) then
149 return 1;
150 else
151 return 0;
155 ------------------------------------------------------------------------------------------------------------
156 -- Update player pvp tag
157 function game:pvpTagUpdateDisplay()
158 local currentServerTick = getDbPropU('UI:VARIABLES:CURRENT_SERVER_TICK');
159 local pvpServerTagTimer = getDbPropU('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:ACTIVATION_TIME');
160 local pvpServerFlagTimer = getDbPropU('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:FLAG_PVP_TIME_LEFT');
161 local uiPlayer= getUI('ui:interface:player:header_opened');
163 -- get the current state
164 local pvpServerFlag= pvpServerFlagTimer > currentServerTick;
165 local pvpLocalTag= (getDbProp('UI:TEMP:PVP_FACTION:TAG_PVP') == 1);
166 local pvpServerTag= (getDbProp('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:TAG_PVP') == 1);
167 local pvpServerActivateTimerOn= pvpServerTagTimer > currentServerTick;
169 -- deduce the display state according to the current state
170 local GREEN= 0;
171 local ORANGE= 1;
172 local RED= 2;
173 local buttonMode= GREEN;
174 local buttonPushed= false;
175 local buttonTimer= false;
176 -- if the flag is activated, then must display PVP flag button and timer
177 if (pvpServerFlag) then
178 -- ** RED MODE
179 buttonMode= RED;
180 buttonPushed= false;
181 buttonTimer= true;
182 -- else must display correct mode according to the TAG state
183 else
184 -- There are 8 possibilities according to the combination of the 3 flags
185 -- Here: TL= pvpLocalTag, TS= pvpServerTag, AS= pvpServerActivateTimerOn)
186 -- TL TS AS
187 -- ** GREEN MODE **
188 -- 0 0 0 -> Standard disabled PVP
189 -- 1 0 0 -> The user pressed the button but still no response from server
190 -- 1 1 1 -> The user pressed the button and got response from server. => GREEN icon with timer
191 -- 0 1 1 -> The user canceled the activation (server not acked yet the cancel). => default display
192 -- ** ORANGE MODE **
193 -- 1 1 0 -> Standard enabled PVP
194 -- 0 1 0 -> The user pressed the button but still no response from server
195 -- 0 0 1 -> The user pressed the button and got response from server. => ORANGE icon with timer
196 -- 1 0 1 -> The user canceled the activation (server not acked yet the cancel). => default display
198 -- From this table, we can deduce the following rules
200 -- buttonMode is GREEN when TS==AS
201 if( pvpServerTag == pvpServerActivateTimerOn ) then
202 buttonMode= GREEN;
203 else
204 buttonMode= ORANGE;
207 -- the button is pushed if (there is a timer and TL==TS), or (no timer and TL!=TS)
208 if( pvpServerActivateTimerOn == (pvpLocalTag == pvpServerTag) ) then
209 buttonPushed= true;
210 else
211 buttonPushed= false;
214 -- display a timer only if the timer is activated and server and local tag are equals
215 if( pvpServerActivateTimerOn and pvpLocalTag == pvpServerTag ) then
216 buttonTimer= true;
217 else
218 buttonTimer= false;
223 -- setup the local display
224 setDbProp("UI:TEMP:PVP_FACTION:DSP_MODE", buttonMode);
225 setDbProp("UI:TEMP:PVP_FACTION:DSP_PUSHED", booleanToNumber(buttonPushed));
226 setDbProp("UI:TEMP:PVP_FACTION:DSP_TIMER", booleanToNumber(buttonTimer));
228 -- setup the timer bar
229 if(buttonTimer) then
230 local uiBar = uiPlayer.pvp_timer;
231 local uiBarBg = uiPlayer.pvp_timer_bg;
232 -- Flag Bar?
233 if(buttonMode==RED) then
234 -- display a reverse timer
235 uiBar.w = uiBarBg.w * (pvpServerFlagTimer - currentServerTick) / (pvpServerFlagTimer - game.PVP.flagStartTimer);
236 else
237 -- display a forward timer
238 uiBar.w = uiBarBg.w * (currentServerTick - game.PVP.tagStartTimer) / (pvpServerTagTimer - game.PVP.tagStartTimer);
242 -- force update of the tooltip for any button (by disabling then reenabling)
243 disableContextHelpForControl(uiPlayer.pvp_tag_button_0);
244 disableContextHelpForControl(uiPlayer.pvp_tag_button_1);
245 disableContextHelpForControl(uiPlayer.pvp_tag_button_2);
248 ------------------------------------------------------------------------------------------------------------
249 -- Update player pvp tag
250 function game:pvpTag()
251 local buttonStat = getDbProp('UI:TEMP:PVP_FACTION:TAG_PVP');
252 if (buttonStat == 0) then
253 setDbProp('UI:TEMP:PVP_FACTION:TAG_PVP',1);
254 else
255 setDbProp('UI:TEMP:PVP_FACTION:TAG_PVP',0);
257 sendMsgToServerPvpTag(buttonStat == 0);
259 -- update display
260 self:pvpTagUpdateDisplay();
263 ------------------------------------------------------------------------------------------------------------
264 -- Update button due to server validation
265 function game:updatePvpTag()
266 -- force copy to temp of Server tag
267 local pvpServerTag= (getDbProp('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:TAG_PVP') == 1);
268 setDbProp('UI:TEMP:PVP_FACTION:TAG_PVP', booleanToNumber(pvpServerTag));
270 -- launch timer DB if necessary
271 local currentServerTick = getDbPropU('UI:VARIABLES:CURRENT_SERVER_TICK');
272 local pvpServerTagTimer = getDbPropU('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:ACTIVATION_TIME');
273 local pvpServerFlagTimer = getDbPropU('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:FLAG_PVP_TIME_LEFT');
275 if(pvpServerTagTimer > currentServerTick) or (pvpServerFlagTimer > currentServerTick) then
276 local ui = getUI('ui:interface:player');
277 addOnDbChange(ui,'@UI:VARIABLES:CURRENT_SERVER_TICK', 'game:updatePvpTimer()');
279 if(pvpServerTagTimer > currentServerTick and game.PVP.tagTimerStarted == false) then
280 game.PVP.tagStartTimer = currentServerTick;
281 game.PVP.tagTimerStarted = true;
283 if(pvpServerFlagTimer > currentServerTick and game.PVP.flagTimerStarted == false) then
284 game.PVP.flagStartTimer = currentServerTick;
285 game.PVP.flagTimerStarted = true;
289 -- update display (after start timer reseted)
290 self:pvpTagUpdateDisplay();
293 ------------------------------------------------------------------------------------------------------------
295 function game:updatePvpTimer()
297 -- update display
298 self:pvpTagUpdateDisplay();
300 -- try to stop
301 local currentServerTick = getDbPropU('UI:VARIABLES:CURRENT_SERVER_TICK');
302 local pvpServerTagTimer = getDbPropU('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:ACTIVATION_TIME');
303 local pvpServerFlagTimer = getDbPropU('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:FLAG_PVP_TIME_LEFT');
305 -- Manage Tag Timer display
306 if(pvpServerTagTimer <= currentServerTick) then
307 game.PVP.tagTimerStarted = false;
310 -- Manage Flag Timer display
311 if(pvpServerFlagTimer <= currentServerTick) then
312 game.PVP.flagTimerStarted = false;
315 -- if both off, stop the db update
316 if(game.PVP.tagTimerStarted == false) and (game.PVP.flagTimerStarted == false) then
317 removeOnDbChange(getUI('ui:interface:player'),'@UI:VARIABLES:CURRENT_SERVER_TICK');
321 ------------------------------------------------------------------------------------------------------------
323 function game:formatTime(temps)
325 local hours = math.floor(temps/(10*60*60));
326 local minutes = math.floor((temps - (hours*10*60*60)) / (10*60));
327 local seconds = math.floor((temps - (hours*10*60*60) - (minutes*10*60)) / 10);
329 local fmt = i18n.get('uittPvPTime');
330 fmt = findReplaceAll(fmt, '%h', tostring(hours));
331 fmt = findReplaceAll(fmt, '%m', tostring(minutes));
332 fmt = findReplaceAll(fmt, '%s', tostring(seconds));
333 return fmt;
336 ------------------------------------------------------------------------------------------------------------
338 function game:playerTTPvp()
340 -- The tooltip to display depends on the current display state
341 local buttonMode= getDbProp("UI:TEMP:PVP_FACTION:DSP_MODE");
342 local buttonPushed= (getDbProp("UI:TEMP:PVP_FACTION:DSP_PUSHED")==1);
343 local buttonTimer= (getDbProp("UI:TEMP:PVP_FACTION:DSP_TIMER")==1);
344 local text;
346 -- Flag mode?
347 if(buttonMode==2) then
348 local pvpServerFlagTimer = getDbPropU('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:FLAG_PVP_TIME_LEFT');
349 local currentServerTick = getDbPropU('UI:VARIABLES:CURRENT_SERVER_TICK');
350 local tempsString = game:formatTime( pvpServerFlagTimer - currentServerTick );
351 text = i18n.get('uittPvPModeFlag');
352 text = findReplaceAll(text, '%temps', tempsString);
353 -- Tag mode
354 else
355 -- base text
356 if(buttonMode==0 and not(buttonPushed)) then
357 text = i18n.get('uittPvPModeTagOff');
358 elseif(buttonMode==0 and buttonPushed) then
359 text = i18n.get('uittPvPModeTagOffChange');
360 elseif(buttonMode==1 and not(buttonPushed)) then
361 text = i18n.get('uittPvPModeTagOn');
362 elseif(buttonMode==1 and buttonPushed) then
363 text = i18n.get('uittPvPModeTagOnChange');
364 else
365 text = ucstring();
367 -- timer
368 if(buttonTimer) then
369 local pvpServerTagTimer = getDbPropU('SERVER:CHARACTER_INFO:PVP_FACTION_TAG:ACTIVATION_TIME');
370 local currentServerTick = getDbPropU('UI:VARIABLES:CURRENT_SERVER_TICK');
371 local tempsString = game:formatTime( pvpServerTagTimer - currentServerTick );
372 local timeFmt= i18n.get('uittPvPTagTimer');
373 timeFmt= findReplaceAll(timeFmt, '%temps', tempsString);
374 text= concatUCString(text, timeFmt);
378 -- set the text
379 setContextHelpText(text);
384 -- ***************************************************************************
385 -- ***************************************************************************
386 -- BONUS MALUS
387 -- ***************************************************************************
388 -- ***************************************************************************
391 ------------------------------------------------------------------------------------------------------------
392 function game:bonusMalusActiveText(ui, slot, state)
393 local uiTextGroup= ui["text" .. tostring(slot) ];
394 if(uiTextGroup) then
395 uiTextGroup.active= state;
399 ------------------------------------------------------------------------------------------------------------
400 function game:bonusMalusSetText(ui, slot, fmt)
401 local uiTextGroup= ui["text" .. tostring(slot) ];
402 if(uiTextGroup) then
403 uiTextGroup.shade0.uc_hardtext_format= fmt;
404 uiTextGroup.shade1.uc_hardtext_format= fmt;
405 uiTextGroup.shade2.uc_hardtext_format= fmt;
406 uiTextGroup.shade3.uc_hardtext_format= fmt;
407 uiTextGroup.text.uc_hardtext_format= fmt;
408 uiTextGroup.text2.uc_hardtext_format= fmt;
412 ------------------------------------------------------------------------------------------------------------
413 -- Called from c++ to format icon regen timer text
414 -- timer: number, ie 123, -123
415 -- dbPath: UI:VARIABLES:BONUS:0
417 -- Activate it in "bonuses" and/or "maluses" xml group.
418 -- If using color tags, then also set both colors to white
419 -- regen_text_fct="lua:game:formatRegenTimer"
420 -- regen_text_color="255 255 255"
421 -- regen_text_disabled_color="255 255 255"
422 function game:formatRegenTimer(timer, dbPath)
423 if timer > 60 then
424 return string.format("%dm", timer / 60);
425 else
426 return string.format("%ds", timer);
430 ------------------------------------------------------------------------------------------------------------
431 -- From given DB vals, compute the 'Xp Bonus' text info
432 function game:updateXpCatQuantity(textSlot, ui)
433 -- get the ui text to fill
434 if(ui==nil) then
435 ui= getUICaller();
438 -- format the text
439 local fmt= "x@{FF6F}" .. tostring( getDbProp("SERVER:CHARACTER_INFO:XP_CATALYSER:Count") );
441 self:bonusMalusSetText(ui, textSlot, fmt);
445 ------------------------------------------------------------------------------------------------------------
446 -- From given DB vals, compute the 'Ring Xp Bonus' text info
447 function game:updateRingXpCatQuantity(textSlot, ui)
448 -- get the ui text to fill
449 if(ui==nil) then
450 ui= getUICaller();
453 -- format the text
454 local fmt= "x@{FF6F}" .. tostring( getDbProp("SERVER:CHARACTER_INFO:RING_XP_CATALYSER:Count") );
456 self:bonusMalusSetText(ui, textSlot, fmt);
460 ------------------------------------------------------------------------------------------------------------
461 function game:outpostUpdatePVPTimer(textSlot, ui)
462 -- get the ui text to fill
463 if(ui==nil) then
464 ui= getUICaller();
467 -- Get the timer of interest (priority to player leaving the zone)
468 local endTimer= 0;
469 local endOfPvpTimer= getDbPropU('SERVER:CHARACTER_INFO:PVP_OUTPOST:FLAG_PVP_TIME_END');
470 if( endOfPvpTimer>0 ) then
471 endTimer= endOfPvpTimer;
472 else
473 local endOfRound= getDbProp('SERVER:CHARACTER_INFO:PVP_OUTPOST:ROUND_END_DATE');
474 if( endOfRound>0 ) then
475 endTimer= endOfRound;
479 -- Use a text with a timer?
480 if( endTimer>0 ) then
481 -- compute the time that lefts in sec (suppose a smooth server tick is 1 ms)
482 local curTick= getDbPropU('UI:VARIABLES:CURRENT_SERVER_TICK');
483 local timeSec= (endTimer- curTick)/10;
484 -- replace in str
485 local text= "@{FF6F}" .. runFct('secondsToTimeStringShort', timeSec);
486 self:bonusMalusSetText(ui, textSlot, text);
487 -- else Default display
488 else
489 self:bonusMalusSetText(ui, textSlot, "@{FF6F}on");
495 ------------------------------------------------------------------------------------------------------------
496 function game:deathPenaltyUpdateXPMalus()
500 ------------------------------------------------------------------------------------------------------------
501 -- called when someone click on a bonus malus icon. redirect to correct action handler if any
502 function game:onLeftClickBonus()
503 local ui= getUICaller();
504 local id= getIndexInDB(ui);
505 local ah= self.BonusMalus.BonusAHList[id];
506 if(ui and ah) then
507 runAH(ui, ah, "");
511 function game:onLeftClickMalus()
512 local ui= getUICaller();
513 local id= getIndexInDB(ui);
514 local ah= self.BonusMalus.MalusAHList[id];
515 if(ui and ah) then
516 runAH(ui, ah, "");
520 ------------------------------------------------------------------------------------------------------------
521 -- update if needed the ActionHandler and text update from DB
522 function game:updateBonusMalusTextSetup()
523 local numLocalBonusMalus= tonumber(getDefine("num_local_bonus_malus"));
524 local uiBonus= getUI('ui:interface:bonus_malus:header_opened:bonus');
525 local uiMalus= getUI('ui:interface:bonus_malus:header_opened:malus');
526 local dbXpCat= "@SERVER:CHARACTER_INFO:XP_CATALYSER:Count";
527 local dbRingXpCat= "@SERVER:CHARACTER_INFO:RING_XP_CATALYSER:Count";
528 local dbOutpost= "@SERVER:CHARACTER_INFO:PVP_OUTPOST, @UI:VARIABLES:CURRENT_SERVER_TICK";
529 local dbDeathPenalty= "@SERVER:USER:DEATH_XP_MALUS";
532 -- reset cache
533 self.BonusMalus.DeathPenaltyBefore= self.BonusMalus.DeathPenaltyAfter;
534 self.BonusMalus.XPCatSlotBefore= self.BonusMalus.XPCatSlotAfter;
535 self.BonusMalus.RingXPCatSlotBefore= self.BonusMalus.RingXPCatSlotAfter;
536 self.BonusMalus.OutpostSlotBefore= self.BonusMalus.OutpostSlotAfter;
539 -- *** remove and hide any preceding
540 for i= 0,numLocalBonusMalus-1 do
541 -- reset AH
542 self.BonusMalus.BonusAHList[i]= nil;
543 self.BonusMalus.MalusAHList[i]= nil;
544 -- hide text view
545 self:bonusMalusActiveText(uiBonus, i, false);
546 -- reset special tooltip
547 setDbProp( formatUI('UI:VARIABLES:BONUS:#1:SPECIAL_TOOLTIP', i), game.TBonusMalusSpecialTT.None);
549 removeOnDbChange(uiBonus, dbXpCat);
550 removeOnDbChange(uiBonus, dbRingXpCat);
551 removeOnDbChange(uiBonus, dbOutpost);
554 -- *** set new XPCat setup
555 local slot= self.BonusMalus.XPCatSlotAfter;
556 if(slot~=-1) then
557 -- set AH to use for this slot
558 self.BonusMalus.BonusAHList[slot]= "xp_catalyser_stop_use";
559 -- add DB change, and call now! else not updated
560 addOnDbChange(uiBonus, dbXpCat, formatUI("game:updateXpCatQuantity(#1, nil)", slot) );
561 self:updateXpCatQuantity(slot, uiBonus);
562 -- show text
563 self:bonusMalusActiveText(uiBonus, slot, true);
564 -- set special tooltip (id==1 for xpcat)
565 setDbProp( formatUI('UI:VARIABLES:BONUS:#1:SPECIAL_TOOLTIP', slot), game.TBonusMalusSpecialTT.XpCatalyser);
568 -- *** set new RingXPCat setup
569 local slot= self.BonusMalus.RingXPCatSlotAfter;
570 if(slot~=-1) then
571 -- set AH to use for this slot
572 self.BonusMalus.BonusAHList[slot]= "ring_xp_catalyser_stop_use";
573 -- add DB change, and call now! else not updated
574 addOnDbChange(uiBonus, dbRingXpCat, formatUI("game:updateRingXpCatQuantity(#1, nil)", slot) );
575 self:updateRingXpCatQuantity(slot, uiBonus);
576 -- show text
577 self:bonusMalusActiveText(uiBonus, slot, true);
578 -- set special tooltip (id==1 for ringxpcat)
579 setDbProp( formatUI('UI:VARIABLES:BONUS:#1:SPECIAL_TOOLTIP', slot), game.TBonusMalusSpecialTT.XpCatalyser);
583 -- *** set new Outpost setup
584 local slot= self.BonusMalus.OutpostSlotAfter;
585 if(slot~=-1) then
586 -- no AH
587 -- add DB change, and call now! else not updated
588 addOnDbChange(uiBonus, dbOutpost, formatUI("game:outpostUpdatePVPTimer(#1, nil)", slot) );
589 self:outpostUpdatePVPTimer(slot, uiBonus);
590 -- show text
591 self:bonusMalusActiveText(uiBonus, slot, true);
592 -- don't set the tooltip here, because redone after return
596 -- *** set new DeathPenalty setup
597 local slot= self.BonusMalus.DeathPenaltyAfter;
598 if(slot~=-1) then
599 -- no AH
600 -- add DB change, and call now! else not updated
601 addOnDbChange(uiMalus, dbDeathPenalty, formatUI("game:deathPenaltyUpdateXPMalus(#1, nil)", slot) );
602 self:deathPenaltyUpdateXPMalus(slot, uiMalus);
603 -- show text
604 self:bonusMalusActiveText(uiMalus, slot, true);
605 -- set special tooltip (id==1 for death penalty)
606 setDbProp( formatUI('UI:VARIABLES:MALUS:#1:SPECIAL_TOOLTIP', slot), game.TBonusMalusSpecialTT.DeathPenalty);
611 ------------------------------------------------------------------------------------------------------------
612 -- Update Bonus malus local DB according to server DB
613 function game:updatePlayerBonusMalus()
614 local numServerBonusMalus= tonumber(getDefine("num_server_bonus_malus"));
615 local numLocalBonusMalus= tonumber(getDefine("num_local_bonus_malus"));
616 local dbServerBonusBase= getDefine("bonus") .. ":" ;
617 local dbServerMalusBase= getDefine("malus") .. ":" ;
618 local dbLocalBonusBase= "UI:VARIABLES:BONUS:";
619 local dbLocalMalusBase= "UI:VARIABLES:MALUS:";
621 local i;
622 local mustUpdateTextSetup= false;
625 -- ***********************
626 -- *** Insert Bonus
627 -- ***********************
628 local destIndex= 0;
629 local mustShowBonus= false;
631 -- *** Insert XPCatalyzer first
632 local xpcatCount= getDbProp("SERVER:CHARACTER_INFO:XP_CATALYSER:Count");
633 if(xpcatCount~=0) then
634 local xpcatLevel= getDbProp("SERVER:CHARACTER_INFO:XP_CATALYSER:Level");
635 -- Get the most appropriate icon
636 local iconLevel= 50;
637 for i= 50,250,50 do
638 if(i<=xpcatLevel) then
639 iconLevel= i;
642 -- Set the DB for this brick
643 mustShowBonus= true;
644 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":SHEET", getSheetId('big_xpcat_' .. tostring(iconLevel) .. '.sbrick' ) );
645 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":DISABLED", 0 );
646 self.BonusMalus.XPCatSlotAfter = destIndex;
647 destIndex= destIndex+1;
648 else
649 self.BonusMalus.XPCatSlotAfter = -1;
651 if(self.BonusMalus.XPCatSlotAfter ~= self.BonusMalus.XPCatSlotBefore) then
652 mustUpdateTextSetup= true;
655 -- *** Then insert RingXPCatalyzer
656 local ringxpcatCount= getDbProp("SERVER:CHARACTER_INFO:RING_XP_CATALYSER:Count");
657 if(ringxpcatCount~=0) then
658 local ringxpcatLevel= getDbProp("SERVER:CHARACTER_INFO:RING_XP_CATALYSER:Level");
659 -- Get the most appropriate icon
660 local iconLevel= 50;
661 for i= 50,250,50 do
662 if(i<=ringxpcatLevel) then
663 iconLevel= i;
666 -- Set the DB for this brick
667 mustShowBonus= true;
668 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":SHEET", getSheetId('big_ring_xpcat_' .. tostring(iconLevel) .. '.sbrick' ) );
669 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":DISABLED", 0 );
670 self.BonusMalus.RingXPCatSlotAfter = destIndex;
671 destIndex= destIndex+1;
672 else
673 self.BonusMalus.RingXPCatSlotAfter = -1;
675 if(self.BonusMalus.RingXPCatSlotAfter ~= self.BonusMalus.RingXPCatSlotBefore) then
676 mustUpdateTextSetup= true;
680 -- *** Insert PVPOutpost
681 local pvpOutpostPresent= getDbProp("SERVER:CHARACTER_INFO:PVP_OUTPOST:FLAG_PVP");
682 local pvpOutpostEndOfPVPFlag= 0;
683 local pvpOutpostEndOfRound= 0;
684 if(pvpOutpostPresent~=0) then
685 local pvpOutpostLevel= 0;
686 pvpOutpostEndOfPVPFlag= getDbPropU('SERVER:CHARACTER_INFO:PVP_OUTPOST:FLAG_PVP_TIME_END');
687 pvpOutpostEndOfRound= getDbPropU('SERVER:CHARACTER_INFO:PVP_OUTPOST:ROUND_END_DATE');
688 -- set a level only if we have some round, and if the out timer is not set
689 if(pvpOutpostEndOfRound~=0 and pvpOutpostEndOfPVPFlag==0) then
690 pvpOutpostLevel= 1 + getDbProp('SERVER:CHARACTER_INFO:PVP_OUTPOST:ROUND_LVL_CUR');
693 -- Set the DB for this brick
694 mustShowBonus= true;
695 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":SHEET", getSheetId('big_outpost_pvp_' .. tostring(pvpOutpostLevel) .. '.sbrick' ) );
696 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":DISABLED", 0 );
697 self.BonusMalus.OutpostSlotAfter = destIndex;
698 destIndex= destIndex+1;
699 else
700 self.BonusMalus.OutpostSlotAfter = -1;
702 if(self.BonusMalus.OutpostSlotAfter ~= self.BonusMalus.OutpostSlotBefore) then
703 mustUpdateTextSetup= true;
707 -- *** Insert standard Bonus
708 for i=0,numServerBonusMalus-1 do
709 -- get
710 local sheet= getDbProp(dbServerBonusBase .. tostring(i) .. ":SHEET" );
711 local disabled= getDbProp(dbServerBonusBase .. tostring(i) .. ":DISABLED" );
712 local timer = getDbProp(dbServerBonusBase .. tostring(i) .. ":DISABLED_TIME" );
713 if(sheet~=0) then
714 mustShowBonus= true;
716 -- copy (to index shifted if needed)
717 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":SHEET", sheet );
718 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":DISABLED", disabled );
719 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":DISABLED_TIME", timer);
720 destIndex= destIndex+1;
722 if(mustShowBonus) then
723 setDbProp("UI:VARIABLES:SHOW_BONUS", 1);
724 else
725 setDbProp("UI:VARIABLES:SHOW_BONUS", 0);
729 -- *** erase any remaining bonus
730 while destIndex<numLocalBonusMalus do
731 setDbProp(dbLocalBonusBase .. tostring(destIndex) .. ":SHEET", 0 );
732 destIndex= destIndex + 1;
737 -- ***********************
738 -- *** Insert Malus
739 -- ***********************
740 local mustShowMalus= false;
741 destIndex= 0;
743 -- *** Insert Death Penalty first
744 local deathPenalty= getDbProp("SERVER:USER:DEATH_XP_MALUS");
745 if(deathPenalty~=255 and deathPenalty~=0) then
746 -- Set the DB for this brick
747 mustShowMalus= true;
748 setDbProp(dbLocalMalusBase .. tostring(destIndex) .. ":SHEET", getSheetId('death_penalty.sbrick' ) );
749 setDbProp(dbLocalMalusBase .. tostring(destIndex) .. ":DISABLED", 0 );
750 self.BonusMalus.DeathPenaltyAfter = destIndex;
751 destIndex= destIndex+1;
752 else
753 self.BonusMalus.DeathPenaltyAfter = -1;
755 if(self.BonusMalus.DeathPenaltyAfter ~= self.BonusMalus.DeathPenaltyBefore) then
756 mustUpdateTextSetup= true;
759 -- *** insert standard malus
760 for i=0,numServerBonusMalus-1 do
761 -- get
762 local sheet= getDbProp(dbServerMalusBase .. tostring(i) .. ":SHEET" );
763 local disabled= getDbProp(dbServerMalusBase .. tostring(i) .. ":DISABLED" );
764 local timer = getDbProp(dbServerMalusBase .. tostring(i) .. ":DISABLED_TIME" );
765 if(sheet~=0) then
766 mustShowMalus= true;
768 -- copy
769 setDbProp(dbLocalMalusBase .. tostring(destIndex) .. ":SHEET", sheet );
770 setDbProp(dbLocalMalusBase .. tostring(destIndex) .. ":DISABLED", disabled );
771 setDbProp(dbLocalMalusBase .. tostring(destIndex) .. ":DISABLED_TIME", timer);
772 destIndex= destIndex+1;
774 if(mustShowMalus) then
775 setDbProp("UI:VARIABLES:SHOW_MALUS", 1);
776 else
777 setDbProp("UI:VARIABLES:SHOW_MALUS", 0);
781 -- *** erase any remaining malus
782 while destIndex<numLocalBonusMalus do
783 setDbProp(dbLocalMalusBase .. tostring(destIndex) .. ":SHEET", 0 );
784 destIndex = destIndex + 1;
789 -- ***********************
790 -- *** update Text setup
791 -- ***********************
792 if(mustUpdateTextSetup) then
793 game:updateBonusMalusTextSetup();
796 -- set special tooltip for outpost (id==2,3,4 for outpost)
797 if(self.BonusMalus.OutpostSlotAfter ~= -1) then
798 local dbFmt= formatUI('UI:VARIABLES:BONUS:#1:SPECIAL_TOOLTIP', self.BonusMalus.OutpostSlotAfter);
799 if(pvpOutpostEndOfPVPFlag ~= 0) then
800 setDbProp(dbFmt, game.TBonusMalusSpecialTT.OutpostPVPOutOfZone);
801 elseif(pvpOutpostEndOfRound ~= 0) then
802 setDbProp(dbFmt, game.TBonusMalusSpecialTT.OutpostPVPInRound);
803 else
804 setDbProp(dbFmt, game.TBonusMalusSpecialTT.OutpostPVPOn);
812 -- ***************************************************************************
813 -- ***************************************************************************
814 -- CURRENT ACTION
815 -- ***************************************************************************
816 -- ***************************************************************************
819 ------------------------------------------------------------------------------------------------------------
820 function game:updateCurrentActionPosition()
821 local uiMemory= getUI("ui:interface:gestionsets");
822 local uiAction= getUI("ui:interface:current_action");
823 local uiMain= getUI("ui:interface");
824 if(uiAction and uiMain and uiMemory and uiMemory.active) then
826 -- NB: must use harcoded 182 and 40 size for the window, because may not be active at this time
828 -- refresh the x position
829 uiAction.x= uiMemory.x_real + uiMemory.w_real/2 - 182/2;
831 -- setup the y position according to position of the memory bar
832 local distBelow= uiMemory.y_real;
833 local distAbove= uiMain.h - (uiMemory.y_real + uiMemory.h_real);
834 if(distBelow < distAbove) then
835 uiAction.y= uiMemory.y_real + uiMemory.h_real + 40;
836 else
837 uiAction.y= uiMemory.y_real;
844 LastTooltipPhrase = nil
846 ------------------------------------------------------------------------------------------------------------
847 -- tool function used by game:updatePhraseTooltip
848 function game:setPhraseTooltipCarac(ttWin, name, value, textValue)
849 local icon = ttWin:find(name)
850 local text = ttWin:find(name .. "_text")
851 if value == 0 then
852 icon.active = false
853 text.active = false
854 else
855 icon.active = true
856 text.active = true
857 if textValue ~= nil then
858 text.uc_hardtext = textValue
859 else
860 text.hardtext = tostring(value)
866 function game:timeInSecondsToReadableTime(regenTime)
867 local seconds = math.fmod(regenTime, 60)
868 local minutes = math.fmod(math.floor(regenTime / 60), 60)
869 local hours = math.floor(regenTime / 3600)
870 local result = ""
871 if seconds > 0 then result = concatUCString(tostring(seconds), i18n.get("uittSecondsShort")) end
872 if minutes > 0 then result = concatUCString(tostring(minutes), i18n.get("uittMinutesShort"), result) end
873 if hours > 0 then result = concatUCString(tostring(hours), i18n.get("uittHoursShort"), result) end
874 return result
877 ------------------------------------------------------------------------------------------------------------
878 -- display the time left for a power / auras in its tooltip
879 function game:setPhraseTooltipPowerRegenTime(ttWin, regenTimeInTicks)
880 local text = ttWin:find("regen_time")
881 if regenTimeInTicks == 0 then
882 text.active = false
883 else
884 text.active = true
885 text.uc_hardtext_single_line_format = concatUCString(i18n.get("uittRegenTime"), game:timeInSecondsToReadableTime(math.floor((regenTimeInTicks + 9) * 0.1)))
886 text:invalidateCoords()
887 ttWin:invalidateCoords()
892 local EmptyUCString = ucstring()
894 ------------------------------------------------------------------------------------------------------------
895 -- called by C++ code when the tooltip of a phrase is about to be displayed
896 function game:updatePhraseTooltip(phrase)
897 LastTooltipPhrase = phrase
898 local ttWin = getUI("ui:interface:action_context_help")
899 local text = phrase:getName()
901 if not text or text == EmptyUCString then
902 text = ucstring("")
905 local desc = phrase:getDesc()
906 if desc and desc ~= EmptyUCString then
907 local str = tostring(desc)
908 local charFound = false
909 for k = 1, string.len(str) do
910 if string.byte(str, k) ~= 32 then
911 charFound = true
912 break
915 if charFound then
916 text = concatUCString(text, "\n@{CCCF}", desc)
918 else
919 text = concatUCString(text, "@{CCCF}")
921 -- IMPORTANT : the following getters on 'phrase' take in account the 'total action malus' for the timebeing
922 self:setPhraseTooltipCarac(ttWin, "hp_cost", phrase:getHpCost())
923 self:setPhraseTooltipCarac(ttWin, "sta_cost", phrase:getStaCost())
924 self:setPhraseTooltipCarac(ttWin, "sap_cost", phrase:getSapCost())
925 self:setPhraseTooltipCarac(ttWin, "focus_cost", phrase:getFocusCost())
926 self:setPhraseTooltipCarac(ttWin, "cast_time", phrase:getCastTime(), concatUCString(string.format("%.1f", phrase:getCastTime()), i18n.get("uittSeconds")))
927 local castRange = phrase:getCastRange()
928 if not phrase:isMagicPhrase() then
929 castRange = 0
931 self:setPhraseTooltipCarac(ttWin, "cast_range", castRange, concatUCString(tostring(castRange), i18n.get("uittMeters")))
932 -- if the phrase is a power / aura, then we may want to display its regen time in the tooltip
933 if phrase:isPowerPhrase() then
934 setOnDraw(ttWin, "game:updatePowerPhraseTooltip()")
935 else
936 setOnDraw(ttWin, "")
939 local successRateText = ttWin:find("success_rate")
940 local successRate = phrase:getSuccessRate()
941 if successRate == 0 then
942 successRateText.active = false
943 else
944 successRateText.active = true
945 successRateText.uc_hardtext_single_line_format = concatUCString(i18n.get("uittSuccessRate"), tostring(successRate), " %")
948 local disableTimeText = ttWin:find("disable_time")
949 if phrase:isPowerPhrase() then
950 local disableTime = phrase:getPowerDisableTime()
951 if disableTime == 0 then
952 disableTimeText.active = false
953 else
954 disableTimeText.active = true
955 disableTimeText.uc_hardtext_single_line_format = concatUCString(i18n.get("uittDisableTime"), game:timeInSecondsToReadableTime(disableTime / 10))
957 else
958 disableTimeText.active = false
960 game:updatePowerPhraseTooltip()
961 updateTooltipCoords()
962 return text
965 ------------------------------------------------------------------------------------------------------------
966 -- called at each frame when a power/aura tooltip is displayed,in order to update the regen countdown
967 function game:updatePowerPhraseTooltip()
968 local ttWin = getUI("ui:interface:action_context_help")
969 local leftRegenTime = 0
970 if LastTooltipPhrase:isPowerPhrase() then
971 leftRegenTime = LastTooltipPhrase:getTotalRegenTime() - LastTooltipPhrase:getRegenTime()
973 if leftRegenTime < 0 then
974 leftRegenTime = 0
976 self:setPhraseTooltipPowerRegenTime(ttWin, leftRegenTime)
977 updateTooltipCoords()
981 -- ***************************************************************************
982 -- ***************************************************************************
983 -- CURRENT BUFF ITEM
984 -- ***************************************************************************
985 -- ***************************************************************************
987 ------------------------------------------------------------------------------------------------------------
988 -- called by C++ code when the tooltip of a buff item is about to be displayed
989 function game:updateBuffItemTooltip(buffItem)
990 local ttWin = getUI("ui:interface:buff_item_context_help")
991 local item = buffItem:getItemInfo()
992 local text = buffItem:getName()
994 self:setPhraseTooltipCarac(ttWin, "hp_buff", item.HpBuff)
995 self:setPhraseTooltipCarac(ttWin, "sta_buff", item.StaBuff)
996 self:setPhraseTooltipCarac(ttWin, "sap_buff", item.SapBuff)
997 self:setPhraseTooltipCarac(ttWin, "focus_buff", item.FocusBuff)
998 self:setPhraseTooltipCarac(ttWin, "durability", item.Hp)
999 -- / max
1000 if item.HpMax == 0 then
1001 ttWin:find("durability_sep").active = false
1002 ttWin:find("durability_max").active = false
1003 else
1004 ttWin:find("durability_sep").active = true
1005 ttWin:find("durability_max").active = true
1006 ttWin:find("durability_max").hardtext = item.HpMax
1009 updateTooltipCoords()
1011 return text
1014 -- ***************************************************************************
1015 -- ***************************************************************************
1016 -- CURRENT CRYSTALLIZED SPELL
1017 -- ***************************************************************************
1018 -- ***************************************************************************
1020 ------------------------------------------------------------------------------------------------------------
1021 -- called by C++ code when the tooltip of a cristallized spell is about to be displayed
1022 function game:updateCrystallizedSpellTooltip(crystallizedSpell)
1023 local ttWin = getUI("ui:interface:crystallized_spell_context_help")
1024 local text = crystallizedSpell:getName()
1026 crystallizedSpell:buildCrystallizedSpellListBrick()
1028 updateTooltipCoords()
1029 return text
1032 ------------------------------------------------------------------------------------------------------------
1033 -- update craft window craftplan or item name and description
1034 -- craftphan
1035 -- uiCaller == ui:interface:phrase_faber_execution:header_opened
1036 -- dbPath == UI:PHRASE:FABER:FABER_PLAN:SHEET
1037 -- selected item
1038 -- uiCaller == ui:interface:phrase_faber_execution:header_opened:item_result
1039 -- dbPath == UI:PHRASE:FABER:RESULT_ITEM:SHEET
1040 function game:updatePhraseFaberPreview(dbPath)
1041 local ui= getUICaller();
1042 local sheet = getSheetName(getDbProp(dbPath))
1044 local name = ui:find("name")
1045 if (name ~= nil) then
1046 ui:find("name").uc_hardtext = getSheetLocalizedName(sheet)
1049 local desc = ui:find("desc")
1050 if (desc ~= nil) then
1051 ui:find("desc").uc_hardtext = getSheetLocalizedDesc(sheet)
1056 function game:fixVpx(vpx)
1057 while string.len(vpx) < 16 do
1058 vpx = "0"..vpx
1061 local vpx1 = string.format("%06d", tonumber(vpx:sub(1, string.len(vpx)-2), 16)*256)
1062 local vpx2 = string.format("%06d", tonumber(vpx:sub(string.len(vpx)-1, string.len(vpx)), 16)+tonumber(vpx1:sub(string.len(vpx1)-5, string.len(vpx1))))
1063 local nvpx = vpx1:sub(1, string.len(vpx1)-6)..vpx2:sub(string.len(vpx2)-5, string.len(vpx2))
1064 return nvpx
1067 -- VERSION --
1068 RYZOM_PLAYER_VERSION = 324