FrameworkZ 4.4.2
Provides a framework for Project Zomboid with various systems.
Loading...
Searching...
No Matches
Characters.lua
Go to the documentation of this file.
1--! \page features Features
2--! \section Characters Characters
3--! Characters are the main focus of the game. They are the players that interact with the world. Characters can be given a name, description, faction, age, height, eye color, hair color, etc. They can also be given items and equipment.\n\n
4--! When a player connects to the server, they may create a character and load said character. The character is then saved to the player's data and can be loaded again when the player reconnects. Characters will be saved automatically at predetermined intervals or upon disconnection or when switching characters.\n\n
5--! Characters are not given items in the traditional sense. Instead, they are given items by a unique ID from an item defined in the framework's (or gamemode's or even plugin's) files. This special item definition is then used to create an item instance that is added to the character's inventory. This allows for items to be created dynamically and given to characters. This allows for the same Project Zomboid item to be reused for different purposes.\n\n
6
7--! \page global_variables Global Variables
8--! \section Characters Characters
9--! FrameworkZ.Characters\n
10--! See Characters for the module on characters.\n\n
11--! FrameworkZ.Characters.List\n
12--! A list of all instanced characters in the game.
13
14FrameworkZ = FrameworkZ or {}
15
16--! \brief Characters module for FrameworkZ. Defines and interacts with CHARACTER object.
17--! \class FrameworkZ.Characters
18FrameworkZ.Characters = {}
19FrameworkZ.Characters.__index = FrameworkZ.Characters
21SKIN_COLOR_PALE = 0
22SKIN_COLOR_WHITE = 1
23SKIN_COLOR_TANNED = 2
24SKIN_COLOR_BROWN = 3
25SKIN_COLOR_DARK_BROWN = 4
27HAIR_COLOR_BLACK_R = 0
28HAIR_COLOR_BLACK_G = 0
29HAIR_COLOR_BLACK_B = 0
30HAIR_COLOR_BLONDE_R = 0.9
31HAIR_COLOR_BLONDE_G = 0.9
32HAIR_COLOR_BLONDE_B = 0.6
33HAIR_COLOR_BROWN_R = 0.3
34HAIR_COLOR_BROWN_G = 0.2
35HAIR_COLOR_BROWN_B = 0.2
36HAIR_COLOR_GRAY_R = 0.5
37HAIR_COLOR_GRAY_G = 0.5
38HAIR_COLOR_GRAY_B = 0.5
39HAIR_COLOR_RED_R = 0.9
40HAIR_COLOR_RED_G = 0.4
41HAIR_COLOR_RED_B = 0.1
42HAIR_COLOR_WHITE_R = 1
43HAIR_COLOR_WHITE_G = 1
44HAIR_COLOR_WHITE_B = 1
45
46--! \brief EQUIPMENT_SLOT_HEAD \= "Hat" Enumeration for the character's head slot.
47EQUIPMENT_SLOT_HEAD = "Hat"
55EQUIPMENT_SLOT_VEST = "TorsoExtraVest"
78--! \brief Character class for FrameworkZ.
79--! \class CHARACTER
80local CHARACTER = {}
82
83--! \brief Initialize a character.
84--! \return \string username
85function CHARACTER:Initialize()
86 if not self.isoPlayer then return end
88 local firstConnection = false
89 local characterModData = self.isoPlayer:getModData()["FZ_CHAR"] or nil
90
91 if not self.inventory then
92 local inventory = FrameworkZ.Inventories:New(self.isoPlayer:getUsername())
93 self.inventoryID = inventory:Initialize()
95 end
96
97 if not characterModData then
98 firstConnection = true
100 self.isoPlayer:getModData()["FZ_CHAR"] = {
101 id = self.id or -1,
102 name = self.name or "Unknown",
103 description = self.description or "No description available.",
104 faction = self.faction or FACTION_CITIZEN,
105 age = self.age or 20,
106 height = self.height or 70,
107 eyeColor = self.eyeColor or "Brown",
108 hairColor = self.hairColor or "Brown",
109 skinColor = self.skinColor or "White",
110 physique = self.physique or "Average",
111 weight = self.weight or "125",
112 inventory = self.inventory or {},
113 upgrades = {}
114 }
115
116 if isClient() then
117 self.isoPlayer:transmitModData()
118 end
119 end
120
121 if firstConnection then
122 self:InitializeDefaultItems()
123 end
125 --self:ValidateCharacterData()
126
127 if isClient() then
128 FrameworkZ.Timers:Simple(5, function()
129 sendClientCommand("FZ_CHAR", "initialize", {self.isoPlayer:getUsername()})
130 end)
131 end
133 return FrameworkZ.Characters:Initialize(self.username, self)
134end
135
136function CHARACTER:OnPreLoad()
137 FrameworkZ.Foundation.ExecuteAllHooks("OnCharacterPreLoad", self)
138end
139FrameworkZ.Foundation:AddAllHookHandlers("OnCharacterPreLoad")
140
141function CHARACTER:OnLoad()
142 FrameworkZ.Foundation.ExecuteAllHooks("OnCharacterLoad", self)
143end
144FrameworkZ.Foundation:AddAllHookHandlers("OnCharacterLoad")
145
146function CHARACTER:OnPostLoad(firstLoad)
147 FrameworkZ.Foundation.ExecuteAllHooks("OnCharacterPostLoad", self, firstLoad)
148end
149FrameworkZ.Foundation:AddAllHookHandlers("OnCharacterPostLoad")
150
151--! \brief Save the character's data from the character object.
152--! \param shouldTransmit \boolean (Optional) Whether or not to transmit the character's data to the server.
153--! \return \boolean Whether or not the character was successfully saved.
154function CHARACTER:Save(shouldTransmit)
155 if shouldTransmit == nil then shouldTransmit = true end
156
157 local player = FrameworkZ.Players:GetPlayerByID(self.isoPlayer:getUsername())
158 local characterData = FrameworkZ.Players:GetCharacterDataByID(self.isoPlayer:getUsername(), self.id)
160 if not player or not characterData then return false end
161 FrameworkZ.Players:ResetCharacterSaveInterval()
162
163 -- Save "physical" character inventory
164 local inventory = self.isoPlayer:getInventory():getItems()
165 characterData.INVENTORY_PHYSICAL = {}
166 for i = 0, inventory:size() - 1 do
167 table.insert(characterData.INVENTORY_PHYSICAL, {id = inventory:get(i):getFullType()})
168 end
169
170 -- Save logical character inventory
171 characterData.INVENTORY_LOGICAL = self.inventory.items
172
173 -- Save character equipment
174 characterData.EQUIPMENT_SLOT_HEAD = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_HEAD) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_HEAD):getFullType()} or nil
175 characterData.EQUIPMENT_SLOT_FACE = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_FACE) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_FACE):getFullType()} or nil
176 characterData.EQUIPMENT_SLOT_EARS = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_EARS) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_EARS):getFullType()} or nil
177 characterData.EQUIPMENT_SLOT_BACKPACK = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_BACKPACK) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_BACKPACK):getFullType()} or nil
178 characterData.EQUIPMENT_SLOT_GLOVES = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_GLOVES) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_GLOVES):getFullType()} or nil
179 characterData.EQUIPMENT_SLOT_UNDERSHIRT = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_UNDERSHIRT) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_UNDERSHIRT):getFullType()} or nil
180 characterData.EQUIPMENT_SLOT_OVERSHIRT = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_OVERSHIRT) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_OVERSHIRT):getFullType()} or nil
181 characterData.EQUIPMENT_SLOT_VEST = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_VEST) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_VEST):getFullType()} or nil
182 characterData.EQUIPMENT_SLOT_BELT = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_BELT) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_BELT):getFullType()} or nil
183 characterData.EQUIPMENT_SLOT_PANTS = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_PANTS) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_PANTS):getFullType()} or nil
184 characterData.EQUIPMENT_SLOT_SOCKS = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_SOCKS) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_SOCKS):getFullType()} or nil
185 characterData.EQUIPMENT_SLOT_SHOES = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_SHOES) and {id = self.isoPlayer:getWornItem(EQUIPMENT_SLOT_SHOES):getFullType()} or nil
187 -- Save character position/direction angle
188 characterData.POSITION_X = self.isoPlayer:getX()
189 characterData.POSITION_Y = self.isoPlayer:getY()
190 characterData.POSITION_Z = self.isoPlayer:getZ()
191 characterData.DIRECTION_ANGLE = self.isoPlayer:getDirectionAngle()
194 characterData.STAT_HUNGER = getStats:getHunger()
195 characterData.STAT_THIRST = getStats:getThirst()
196 characterData.STAT_FATIGUE = getStats:getFatigue()
197 characterData.STAT_STRESS = getStats:getStress()
198 characterData.STAT_PAIN = getStats:getPain()
199 characterData.STAT_PANIC = getStats:getPanic()
200 characterData.STAT_BOREDOM = getStats:getBoredom()
201 --characterData.STAT_UNHAPPINESS = getStats:getUnhappyness()
202 characterData.STAT_DRUNKENNESS = getStats:getDrunkenness()
203 characterData.STAT_ENDURANCE = getStats:getEndurance()
204 --characterData.STAT_TIREDNESS = getStats:getTiredness()
205
206 --[[
207 modData.status.health = character:getBodyDamage():getOverallBodyHealth()
208 modData.status.injuries = character:getBodyDamage():getInjurySeverity()
209 modData.status.hyperthermia = character:getBodyDamage():getTemperature()
210 modData.status.hypothermia = character:getBodyDamage():getColdStrength()
211 modData.status.wetness = character:getBodyDamage():getWetness()
212 modData.status.hasCold = character:getBodyDamage():HasACold()
213 modData.status.sick = character:getBodyDamage():getSicknessLevel()
214 --]]
215
216 player:GetStoredData().characters[self.id] = characterData
218 if isClient() and shouldTransmit == true then
219 self.isoPlayer:transmitModData()
220 end
222 return true
223end
224
225--! \brief Destroy a character. This will remove the character from the list of characters and is usually called after a player has disconnected.
226function CHARACTER:Destroy()
227 if isClient() then
228 sendClientCommand("FZ_CHAR", "destroy", {self.isoPlayer:getUsername()})
229 end
231 self.isoPlayer = nil
232end
233
234--! \brief Initialize the default items for a character based on their faction. Called when FZ_CHAR mod data is first created.
235function CHARACTER:InitializeDefaultItems()
236 local faction = FrameworkZ.Factions:GetFactionByID(self.faction)
237
238 if faction then
239 for k, v in pairs(faction.defaultItems) do
240 self:GiveItems(k, v)
241 end
242 end
243end
245--! \brief Validate the character's data.
246--! \return \boolean Whether or not any of the character's new data was initialized.
247function CHARACTER:ValidateCharacterData()
248 local characterModData = self.isoPlayer:getModData()["FZ_CHAR"]
249
250 if not characterModData then return false end
251
252 local initializedNewData = false
253
254 if not characterModData.name then
255 initializedNewData = true
256 characterModData.name = self.name or "Unknown"
257 end
259 if not characterModData.description then
261 characterModData.description = self.description or "No description available."
262 end
263
264 if not characterModData.faction then
265 initializedNewData = true
266 characterModData.faction = self.faction or FACTION_CITIZEN
267 end
269 if not characterModData.age then
271 characterModData.age = self.age or 20
272 end
273
274 if not characterModData.heightFeet then
275 initializedNewData = true
276 characterModData.heightFeet = self.heightFeet or 5
277 end
279 if not characterModData.heightInches then
281 characterModData.heightInches = self.heightInches or 10
282 end
283
284 if not characterModData.eyeColor then
285 initializedNewData = true
286 characterModData.eyeColor = self.eyeColor or "Brown"
287 end
289 if not characterModData.hairColor then
291 characterModData.hairColor = self.hairColor or "Brown"
292 end
293
294 if not characterModData.physique then
295 initializedNewData = true
296 characterModData.physique = self.physique or "Average"
297 end
299 if not characterModData.weight then
301 characterModData.weight = self.weight or "125"
302 end
303
304 if not characterModData.inventory then
305 initializedNewData = true
306 characterModData.inventory = self.inventory or {}
307 end
309 if not characterModData.upgrades then
311 characterModData.upgrades = {}
312 end
313
314 if isClient() then
315 self.isoPlayer:transmitModData()
316 end
317
318 self.name = characterModData.name
319 self.description = characterModData.description
320 self.faction = characterModData.faction
321 self.age = characterModData.age
322 self.heightFeet = characterModData.heightFeet
323 self.heightInches = characterModData.heightInches
324 self.eyeColor = characterModData.eyeColor
325 self.hairColor = characterModData.hairColor
326 self.physique = characterModData.physique
327 self.upgrades = characterModData.upgrades
329 return initializedNewData
330end
331
332--! \brief Set the age of the character.
333--! \param age \integer The age of the character.
334function CHARACTER:SetAge(age)
335 self.age = age
336 self.isoPlayer:getModData()["FZ_CHAR"].age = age
337 self.isoPlayer:transmitModData()
338
339 if isClient() then
340 sendClientCommand("FZ_CHAR", "update", {self.isoPlayer:getUsername(), "age", age})
341 end
342end
343
344--! \brief Set the description of the character.
345--! \param description \string The description of the character's appearance.
346function CHARACTER:SetDescription(description)
347 self.description = description
348 self.isoPlayer:getModData()["FZ_CHAR"].description = description
349 self.isoPlayer:transmitModData()
350
351 if isClient() then
352 sendClientCommand("FZ_CHAR", "update", {self.isoPlayer:getUsername(), "description", description})
353 end
354end
355
356--! \brief Set the faction of the character.
357--! \param faction \string The ID of the faction to set on the character.
358function CHARACTER:SetFaction(faction)
359 self.faction = faction
360 self.isoPlayer:getModData()["FZ_CHAR"].faction = faction
361 self.isoPlayer:transmitModData()
362
363 if isClient() then
364 sendClientCommand("FZ_CHAR", "update", {self.isoPlayer:getUsername(), "faction", faction})
365 end
366end
367
368function CHARACTER:GetName(name)
369 return self.name
370end
371
372--! \brief Set the name of the character.
373--! \param name \string The new name for the character.
374function CHARACTER:SetName(name)
375 self.name = name
376 self.isoPlayer:getModData()["FZ_CHAR"].name = name
377 self.isoPlayer:transmitModData()
378
379 if isClient() then
380 sendClientCommand("FZ_CHAR", "update", {self.isoPlayer:getUsername(), "name", name})
381 end
382end
383
384--! \brief Get the character's inventory object.
385--! \return \table The character's inventory object.
386function CHARACTER:GetInventory()
387 return FrameworkZ.Inventories:GetInventoryByID(self.inventoryID)
388end
389
390--! \brief Give a character items by the specified amount.
391--! \param itemID \string The ID of the item to give.
392--! \param amount \integer The amount of the item to give.
393function CHARACTER:GiveItems(uniqueID, amount)
394 for i = 1, amount do
395 self:GiveItem(uniqueID)
396 end
397end
399--! \brief Give a character an item.
400--! \param uniqueID \string The ID of the item to give.
401--! \return \boolean Whether or not the item was successfully given.
402function CHARACTER:GiveItem(uniqueID)
403 local inventory = self:GetInventory()
405 if inventory then
406 local success, message, itemInstance = FrameworkZ.Items:CreateItem(uniqueID, self.isoPlayer)
407
408 if not success then return false, "Failed to create item." end
409
410 inventory:AddItem(itemInstance)
411
412 if isClient() then
413 --worldItem:transmitModData() -- Only transmit when item is on ground?
414 end
415
416 return true, message, itemInstance
417 end
419 return false, "Failed to find inventory."
420end
421
422--! \brief Take an item from a character's inventory.
423--! \param itemID \string The ID of the item to take.
424--! \return \boolean Whether or not the item was successfully taken.
425function CHARACTER:TakeItem(itemID)
426 local item = FrameworkZ.Items:GetItemByID(itemID)
427
428 if item then
429 local inventory = self.isoPlayer:getInventory()
430 local worldItem = inventory:getFirstTypeRecurse(item.id)
431 local instanceID = worldItem:getModData()["FZ_ITM"].instanceID
432
433 FrameworkZ.Items:RemoveInstance(item.id, instanceID)
434 inventory:DoRemoveItem(worldItem)
435
436 return true
437 end
438
439 return false
440end
441
442--! \brief Take an item from a character's inventory by its instance ID. Useful for taking a specific item from a stack.
443--! \param itemID \string The ID of the item to take.
444--! \param instanceID \integer The instance ID of the item to take.
445--! \return \boolean Whether or not the item was successfully taken.
446function CHARACTER:TakeItemByInstanceID(itemID, instanceID)
447 local item = FrameworkZ.Items:GetItemByID(itemID)
448
449 if item then
450 local inventory = self.isoPlayer:getInventory()
451 local worldItem = inventory:getFirstTypeRecurse(item.id) -- Search whole inventory for matching item instance ID or make an inventory module for more efficiency?
452
453 FrameworkZ.Items:RemoveInstance(item.id, instanceID)
454 inventory:DoRemoveItem(worldItem)
455
456 return true
457 end
458
459 return false
460end
461
462--! \brief Checks if a character is a citizen.
463--! \return \boolean Whether or not the character is a citizen.
464function CHARACTER:IsCitizen()
465 if not self.faction then return false end
466
467 if self.faction == FACTION_CITIZEN then
468 return true
469 end
470
471 return false
472end
473
474--! \brief Checks if a character is a combine.
475--! \return \boolean Whether or not the character is a combine.
476function CHARACTER:IsCombine()
477 if not self.faction then return false end
478
479 if self.faction == FACTION_CP then
480 return true
481 elseif self.faction == FACTION_OTA then
482 return true
483 elseif self.faction == FACTION_ADMINISTRATOR then
484 return true
485 end
486
487 return false
488end
489
490--! \brief Create a new character object.
491--! \param username \string The player's username as their ID.
492--! \param id \integer The character's ID from the player stored data.
493--! \param data \table (Optional) The character's data stored on the object.
494--! \return \table The new character object.
495function FrameworkZ.Characters:New(username, id, data)
496 if not username then return false end
497
498 local object
499
500 if not data then
501 object = {
503 id = id or -1
504 }
505 else
506 object = data
507 object.username = username
508 object.id = id or -1
509 end
510
511 setmetatable(object, CHARACTER)
512
513 return object
514end
515
516--! \brief Initialize a character.
517--! \param username \string The player's username.
518--! \param character \table The character's object data.
519--! \return \string The username added to the list of characters.
520function FrameworkZ.Characters:Initialize(username, character)
522
523 return username
524end
525
526--! \brief Gets the user's loaded character by their ID.
527--! \param username \string The player's username to get their character object with.
528--! \return \table The character object from the list of characters.
529function FrameworkZ.Characters:GetCharacterByID(username)
530 local character = self.List[username] or nil
531
532 return character
533end
534
535function FrameworkZ.Characters:GetCharacterInventoryByID(username)
536 local character = self:GetCharacterByID(username)
537
538 if character then
539 return character:GetInventory()
540 end
541
542 return nil
543end
544
545--! \brief Saves the user's currently loaded character.
546--! \param username \string The player's username to get their loaded character from.
547--! \return \boolean Whether or not the character was successfully saved.
548function FrameworkZ.Characters:Save(username)
549 if not username then return false end
550
551 local character = self:GetCharacterByID(username)
552
553 if character then
554 return character:Save()
555 end
556
557 return false
558end
559
560--! \brief Initializes a player's character after loading.
561--! \return \boolean Whether or not the post load was successful.
562function FrameworkZ.Characters:PostLoad(isoPlayer, characterData)
563 local username = isoPlayer:getUsername()
564
565 local character = FrameworkZ.Characters:New(username, characterData.META_ID)
566
567 if not character then return false end
568
569 character:OnPreLoad()
570
571 FrameworkZ.Characters:CreateCharacterTick(isoPlayer, 1)
573 character.name = characterData.INFO_NAME
574 character.description = characterData.INFO_DESCRIPTION
575 character.faction = characterData.INFO_FACTION
576 character.age = characterData.INFO_AGE
577 character.heightInches = characterData.INFO_HEIGHT
578 character.eyeColor = characterData.INFO_EYE_COLOR
579 character.hairColor = characterData.INFO_HAIR_STYLE
580 character.skinColor = characterData.INFO_SKIN_COLOR
581 character.physique = characterData.INFO_PHYSIQUE
582 character.weight = characterData.INFO_WEIGHT
583
584 local newInventory = FrameworkZ.Inventories:New(username)
585 local success, message, rebuiltInventory = FrameworkZ.Inventories:Rebuild(isoPlayer, newInventory, characterData.INVENTORY_LOGICAL or nil)
586 character.inventory = rebuiltInventory or nil
587
588 if character.inventory then
589 character.inventoryID = character.inventory.id
590 character.inventory:Initialize()
591 end
592
593 character:Initialize()
594
595 FrameworkZ.Timers:Create("FZ_CharacterSaveInterval", FrameworkZ.Config.CharacterSaveInterval, 0, function()
596 local success, message = FrameworkZ.Players:Save(username)
597
598 if success then
600 FrameworkZ.Notifications:AddToQueue("Successfully saved current character.", FrameworkZ.Notifications.Types.Success)
601 end
602 else
603 FrameworkZ.Notifications:AddToQueue(message, FrameworkZ.Notifications.Types.Danger)
604 end
605 end)
606
607 character:OnLoad()
608
609 return true, character
610end
611
612if isClient() then
613
614 local showingTooltip = false
615 local previousMouseX = 0
616 local previousMouseY = 0
617 local tooltipX = 0
618 local tooltipY = 0
619 local tooltipPlayer = nil
620 local tooltip = {name = "", description = {}}
621
622 function FrameworkZ.Characters:GetDescriptionLines(description)
623 local lines = {}
624 local line = ""
625 local lineLength = 0
626 local words = {}
627
628 for word in string.gmatch(description, "%S+") do
629 table.insert(words, word)
630 end
631
632 for i = 1, #words do
633 local word = words[i]
634 local wordLength = string.len(word)
635
636 if lineLength + wordLength <= 30 then
637 line = line .. " " .. word
638 lineLength = lineLength + wordLength
639 else
640 table.insert(lines, line)
641 line = word
642 lineLength = wordLength
643 end
644 end
645
646 table.insert(lines, line)
647
648 return lines
649 end
650
652 if tooltip then
653 local y = tooltipY + getTextManager():getFontFromEnum(UIFont.Dialogue):getLineHeight()
654
655 getTextManager():DrawStringCentre(UIFont.Dialogue, tooltipX, y, tooltip.name, 0.6, 0.5, 0.4, 0.75)
656
657 for k, v in pairs(tooltip.description) do
658 y = y + getTextManager():getFontFromEnum(UIFont.Dialogue):getLineHeight()
659 getTextManager():DrawStringCentre(UIFont.Dialogue, tooltipX, y, v, 1, 1, 1, 0.75)
660 end
661 end
662 end
663
664 function FrameworkZ.Characters:CreateCharacterTick(player, tickTime)
665 FrameworkZ.Timers:Create("CharacterTick", tickTime, 0, function()
666 local x = getMouseX()
667 local y = getMouseY()
668
669 if x ~= previousMouseX or y ~= previousMouseY then
670 Events.OnPreUIDraw.Remove(FrameworkZ.Characters.OnPreUIDraw)
671
672 showingTooltip = false
676 elseif showingTooltip == false then
677 showingTooltip = true
678
679 if player then
680 local playerIndex = player:getPlayerNum()
681 local worldX = screenToIsoX(playerIndex, x, y, 0)
682 local worldY = screenToIsoY(playerIndex, x, y, 0)
683 local worldZ = player:getZ()
684 local square = getSquare(worldX, worldY, worldZ)
685
686 if square then
687 local playerOnSquare = square:getPlayer()
688
689 if playerOnSquare then
690 local playerOnSquareIndex = playerOnSquare:getPlayerNum()
691 tooltipX = isoToScreenX(playerOnSquareIndex, worldX, worldY, worldZ)
692 tooltipY = isoToScreenY(playerOnSquareIndex, worldX, worldY, worldZ)
693
694 tooltipPlayer = playerOnSquare
695 local character = FrameworkZ.Characters:GetCharacterByID(playerOnSquare:getUsername())
696 tooltip.name = character and character.name or "Invalid Character"
697 tooltip.description = FrameworkZ.Characters:GetDescriptionLines(character and character.description or "Invalid Description")
698
699
700 if tooltip then
701 Events.OnPreUIDraw.Add(FrameworkZ.Characters.OnPreUIDraw)
702 end
703 end
704 end
705 end
706 elseif showingTooltip == true then
707 if player then
708 local playerIndex = player:getPlayerNum()
709 local worldX = screenToIsoX(playerIndex, x, y, 0)
710 local worldY = screenToIsoY(playerIndex, x, y, 0)
711 local worldZ = player:getZ()
712 local square = getSquare(worldX, worldY, worldZ)
713
714 if square then
715 local playerOnSquare = square:getPlayer()
716
717 if playerOnSquare ~= tooltipPlayer then
718 Events.OnPreUIDraw.Remove(FrameworkZ.Characters.OnPreUIDraw)
719 showingTooltip = false
721 end
722 end
723 end
724 end
725 end)
726 end
727end
728
729if not isClient() then
730
731 --! \brief Initialize a character called by OnServerStarted event hook.
732 --! \param module \string
733 --! \param command \string
734 --! \param player \table Player object.
735 --! \param args \string
736 function FrameworkZ.Characters.OnClientCommand(module, command, player, args)
737 if module == "FZ_CHAR" then
738 if command == "initialize" then
739 local username = args[1]
740 local character = FrameworkZ.Characters:New(username)
741
743 character:Initialize()
744 elseif command == "destroy" then
745 local username = args[1]
746 local character = FrameworkZ.Characters:GetCharacterByID(username)
747
748 if character then
749 character:Destroy()
750 end
751
752 FrameworkZ.Characters.List[username] = nil
753 elseif command == "update" then
754 local username = args[1]
755 local field = args[2]
756 local newData = args[3]
757
758 FrameworkZ.Characters.List[username][field] = newData
759 end
760 end
761 end
762 Events.OnClientCommand.Add(FrameworkZ.Characters.OnClientCommand)
763end
764
765FrameworkZ.Characters.Meta = CHARACTER
766
767FrameworkZ.Foundation:RegisterModule(FrameworkZ.Characters)
void CharacterSaveInterval()
void FACTION_CITIZEN()
void Factions()
void ShouldNotifyOnCharacterSave()
void FrameworkZ Config()
void local Events()
void gamemode()
void module()
void FrameworkZ Foundation()
void local color()
void local y()
void local x()
void characterData EQUIPMENT_SLOT_FACE()
void inventory()
void id()
void local wordLength()
void characterData INVENTORY_LOGICAL()
void characterData EQUIPMENT_SLOT_GLOVES()
void modData status wetness()
void physique()
void characterData EQUIPMENT_SLOT_VEST()
void characterData EQUIPMENT_SLOT_SHOES()
void description()
void local showingTooltip()
void characterData STAT_BOREDOM()
void hairColor()
void skinColor()
void characterData STAT_ENDURANCE()
void characterData POSITION_Y()
void characterData POSITION_X()
void local success
void characterData EQUIPMENT_SLOT_OVERSHIRT()
void characterData POSITION_Z()
void characterData EQUIPMENT_SLOT_HEAD()
void modData status hasCold()
void characterData EQUIPMENT_SLOT_BACKPACK()
void upgrades()
void characterData STAT_STRESS()
void local previousMouseY()
void eyeColor()
void weight()
void characterData EQUIPMENT_SLOT_UNDERSHIRT()
void characterData EQUIPMENT_SLOT_SOCKS()
void characterData EQUIPMENT_SLOT_BELT()
void modData status hypothermia()
void local tooltipPlayer()
void characterData STAT_PAIN()
void modData status injuries()
void characterData STAT_HUNGER()
void local getStats()
void local previousMouseX()
void player
void characterData STAT_PANIC()
void local message()
void characterData STAT_THIRST()
void local tooltip()
void faction()
void characterModData heightInches()
void age()
void modData status sick()
void initializedNewData()
void characterData EQUIPMENT_SLOT_EARS()
void characterData EQUIPMENT_SLOT_PANTS()
void local tooltipY()
void modData status health()
void name()
void firstConnection()
void self isoPlayer
void characterData STAT_FATIGUE()
void modData status hyperthermia()
void height()
void characterData STAT_DRUNKENNESS()
void for i()
void if isClient() and shouldTransmit()
void characterModData heightFeet()
void local word()
void FrameworkZ()
void characterData DIRECTION_ANGLE()
void local tooltipX()
void FrameworkZ Classes List()
void if self initialFaction and v()
void local instance()
void local worldItem()
void uniqueID()
void items()
void local object()
void itemID()
void local instanceID
void if not description or description()
void self self
Definition MainMenu.lua:85
void self self nil
Definition MainMenu.lua:91
void processingNotification backgroundColor a()
void local position()
void local newData()
void local getPlayer()
void self username()
void local character()
void characterModData characters()
void elseif command()
void local item()
void local field()
void saved()
Character class for FrameworkZ.
table GetInventory()
Get the character's inventory object.
boolean TakeItem(itemID)
Take an item from a character's inventory.
void SetFaction(faction)
Set the faction of the character.
boolean IsCombine()
Checks if a character is a combine.
boolean Save(shouldTransmit)
Save the character's data from the character object.
void SetName(name)
Set the name of the character.
void OnPostLoad(firstLoad)
boolean ValidateCharacterData()
Validate the character's data.
void OnPreLoad()
void GiveItems(uniqueID, amount)
Give a character items by the specified amount.
void SetAge(age)
Set the age of the character.
void SetDescription(description)
Set the description of the character.
boolean IsCitizen()
Checks if a character is a citizen.
void Destroy()
Destroy a character. This will remove the character from the list of characters and is usually called...
boolean TakeItemByInstanceID(itemID, instanceID)
Take an item from a character's inventory by its instance ID. Useful for taking a specific item from ...
string Initialize()
Initialize a character.
void OnLoad()
CHARACTER __index
boolean GiveItem(uniqueID)
Give a character an item.
void GetName(name)
void InitializeDefaultItems()
Initialize the default items for a character based on their faction. Called when FZ_CHAR mod data is ...
Characters module for FrameworkZ. Defines and interacts with CHARACTER object.
void OnClientCommand(module, command, player, args)
Initialize a character called by OnServerStarted event hook.
FrameworkZ Characters EquipmentSlots
table GetCharacterByID(username)
Gets the user's loaded character by their ID.
table New(username, id, data)
Create a new character object.
FrameworkZ Characters __index
void GetDescriptionLines(description)
void CreateCharacterTick(player, tickTime)
FrameworkZ Characters List
void GetCharacterInventoryByID(username)
boolean PostLoad(isoPlayer, characterData)
Initializes a player's character after loading.
string Initialize(username, character)
Initialize a character.
boolean Save(username)
Saves the user's currently loaded character.
EQUIPMENT_SLOT_HEAD
EQUIPMENT_SLOT_HEAD = "Hat" Enumeration for the character's head slot.
Foundation for FrameworkZ.
The Inventories module for FrameworkZ. Defines and interacts with INVENTORY object.
Timers module for FrameworkZ. Allows for the creation of timers for delaying code executions.
Definition Timers.lua:5
FrameworkZ global table.