DungeonCrawl
Loading...
Searching...
No Matches
character.c
Go to the documentation of this file.
1
5#include "character.h"
6
7#include "../combat/ability.h"
8#include "../common.h"
9#include "../logging/logger.h"
10
11#include <stdio.h>
12
13character_t* init_character(memory_pool_t* memory_pool, const character_type_t type, const char* name) {
14 NULL_PTR_HANDLER_RETURN(memory_pool, NULL, "Character", "In init_character memory pool is NULL");
15 NULL_PTR_HANDLER_RETURN(name, NULL, "Character", "In init_character name is NULL");
16
17 character_t* character = memory_pool_alloc(memory_pool, sizeof(character_t));
18 NULL_PTR_HANDLER_RETURN(character, NULL, "Character", "Failed to allocate memory for character: %s", name);
19
20 character->type = type;
21 snprintf(character->name, sizeof(character->name), "%s", name);
22 character->base_stats = (stats_t) {0};
23 character->current_stats = (stats_t) {0};
24 character->max_resources = (resources_t) {0};
25 character->current_resources = (resources_t) {0};
26
27 for (int i = 0; i < DAMAGE_TYPE_COUNT; i++) {
28 character->resistance[i].type = i;
29 character->resistance[i].value = 0;
30 }
31
32 character->defenses = (defenses_t) {0};
33
34 for (int i = 0; i < MAX_ABILITY_LIMIT; i++) {
35 character->abilities[i] = NULL;
36 }
37 character->base_attack = NULL;
38 character->ability_count = 0;
39
40 for (int i = 0; i < MAX_POTION_LIMIT; i++) {
41 character->potion_inventory[i] = NULL;
42 }
43 character->potion_count = 0;
44
45 for (int i = 0; i < MAX_GEAR_LIMIT; i++) {
46 character->gear_inventory[i] = NULL;
47 }
48 character->gear_count = 0;
49
50 for (int i = 0; i < MAX_SLOT; i++) {
51 character->equipment[i] = NULL;
52 }
53 character->level = 0;
54 character->xp = 0;
55 character->xp_reward = 0;
56 character->skill_points = 0;
57 return character;
58}
59
60void free_character(memory_pool_t* memory_pool, character_t* character) {
61 NULL_PTR_HANDLER_RETURN(memory_pool, , "Character", "In free_character memory pool is NULL");
62 NULL_PTR_HANDLER_RETURN(character, , "Character", "In free_character character is NULL");
63 memory_pool_free(memory_pool, character);
64}
65
66void set_character_stats(character_t* character, int strength, int intelligence, int dexterity, int constitution) {
67 NULL_PTR_HANDLER_RETURN(character, , "Character", "In set_character_stats character is NULL");
68
69 set_stats(&character->base_stats, strength, intelligence, dexterity, constitution);
70 character->current_stats = character->base_stats;
71 update_character_resources(&character->current_resources, &character->max_resources, &character->base_stats);
72 character->current_resources = character->max_resources;
73 character->defenses.armor = 0;
74 character->defenses.magic_resist = 0;
75}
76
77void set_stats(stats_t* stats, int strength, int intelligence, int dexterity, int constitution) {
78 NULL_PTR_HANDLER_RETURN(stats, , "Character", "In set_stats stats is NULL");
79
80 stats->strength = strength;
81 stats->intelligence = intelligence;
82 stats->dexterity = dexterity;
83 stats->constitution = constitution;
84}
85
86void update_character_resources(resources_t* current_resources, resources_t* max_resources, stats_t* base_stats) {
87 NULL_PTR_HANDLER_RETURN(current_resources, , "Character", "In update_character_resources current_resources is NULL");
88 NULL_PTR_HANDLER_RETURN(max_resources, , "Character", "In update_character_resources max_resources is NULL");
89 NULL_PTR_HANDLER_RETURN(base_stats, , "Character", "In update_character_resources base_stats is NULL");
90
91 int new_max_health = 5 * base_stats->constitution;
92 int new_max_mana = 1 * base_stats->intelligence;
93 int new_max_stamina = 2 * base_stats->strength;
94
95 if (max_resources->health > 0 && current_resources->health > 0) {
96 current_resources->health = (int) ((double) current_resources->health / max_resources->health * new_max_health + 0.5);
97 }
98 if (max_resources->mana > 0 && current_resources->mana > 0) {
99 current_resources->mana = (int) ((double) current_resources->mana / max_resources->mana * new_max_mana + 0.5);
100 }
101 if (max_resources->stamina > 0 && current_resources->stamina > 0) {
102 current_resources->stamina = (int) ((double) current_resources->stamina / max_resources->stamina * new_max_stamina + 0.5);
103 }
104
105 // Limit current values to new max values
106 current_resources->health = current_resources->health > new_max_health ? new_max_health : current_resources->health;
107 current_resources->mana = current_resources->mana > new_max_mana ? new_max_mana : current_resources->mana;
108 current_resources->stamina = current_resources->stamina > new_max_stamina ? new_max_stamina : current_resources->stamina;
109
110 max_resources->health = new_max_health;
111 max_resources->mana = new_max_mana;
112 max_resources->stamina = new_max_stamina;
113}
114
115void set_character_dmg_modifier(character_t* character, damage_type_t type, int value) {
116 NULL_PTR_HANDLER_RETURN(character, , "Character", "In set_character_dmg_modifier character is NULL");
117
118 for (int i = 0; i < DAMAGE_TYPE_COUNT; i++) {
119 if (character->resistance[i].type == type) {
120 character->resistance[i].value = value;
121 return;
122 }
123 }
124 log_msg(WARNING, "Character", "Unknown damage type: %d", type);
125}
126
127void add_ability(character_t* character, ability_t* ability) {
128 NULL_PTR_HANDLER_RETURN(character, , "Character", "In add_ability character is NULL");
129 NULL_PTR_HANDLER_RETURN(ability, , "Character", "In add_ability ability is NULL");
130
131 if (character->ability_count < MAX_ABILITY_LIMIT) {
132 character->abilities[character->ability_count] = ability;
133 character->ability_count++;
134 } else {
135 log_msg(WARNING, "Character", "%s cannot learn more abilities!", character->name);
136 }
137}
138
139void remove_ability(character_t* character, const ability_t* ability) {
140 NULL_PTR_HANDLER_RETURN(character, , "Character", "In remove_ability character is NULL");
141 NULL_PTR_HANDLER_RETURN(ability, , "Character", "In remove_ability ability is NULL");
142
143 for (int i = 0; i < character->ability_count; i++) {
144 if (character->abilities[i] == ability) {
145 for (int j = i; j < character->ability_count - 1; j++) {
146 character->abilities[j] = character->abilities[j + 1];
147 }
148 character->abilities[character->ability_count - 1] = NULL;
149 character->ability_count--;
150
151 break;
152 }
153 }
154}
155
156void add_gear(character_t* character, gear_t* gear) {
157 NULL_PTR_HANDLER_RETURN(character, , "Character", "In add_gear character is NULL");
158 NULL_PTR_HANDLER_RETURN(gear, , "Character", "In add_gear gear is NULL");
159
160 if (character->gear_count < MAX_GEAR_LIMIT) {
161 character->gear_inventory[character->gear_count] = gear;
162 character->gear_count++;
163
164 } else {
165 log_msg(WARNING, "Character", "%s cannot carry more gear!", character->name);
166 }
167}
168
169void remove_gear(character_t* character, gear_t* gear) {
170 NULL_PTR_HANDLER_RETURN(character, , "Character", "In remove_gear character is NULL");
171 NULL_PTR_HANDLER_RETURN(gear, , "Character", "In remove_gear gear is NULL");
172
173 for (int i = 0; i < character->gear_count; i++) {
174 if (character->gear_inventory[i] == gear) {
175 for (int j = i; j < character->gear_count - 1; j++) {
176 character->gear_inventory[j] = character->gear_inventory[j + 1];
177 }
178 character->gear_inventory[character->gear_count - 1] = NULL;
179 character->gear_count--;
180
181 return;
182 }
183 }
184 log_msg(WARNING, "Character", "Gear %s not found in inventory!", gear->local_key);
185}
186
187void remove_equipped_gear(character_t* character, gear_slot_t slot) {
188 NULL_PTR_HANDLER_RETURN(character, , "Character", "In remove_equipped_gear character is NULL");
189 CHECK_ARG_RETURN(slot < 0 && slot >= MAX_SLOT, , "Character", "In remove_equipped_gear slot is invalid: %d", slot);
190
191 if (character->equipment[slot] != NULL) {
192 gear_t* gear = character->equipment[slot];
193
194 character->base_stats.strength -= gear->stats.strength;
195 character->base_stats.intelligence -= gear->stats.intelligence;
196 character->base_stats.dexterity -= gear->stats.dexterity;
197 character->base_stats.constitution -= gear->stats.constitution;
198 character->defenses.armor -= gear->defenses.armor;
199 character->defenses.magic_resist -= gear->defenses.magic_resist;
200 update_character_resources(&character->current_resources, &character->max_resources, &character->base_stats);
201
202 for (int i = 0; i < gear->num_abilities; ++i) {
203 remove_ability(character, gear->abilities[i]);
204 }
205
206 if (character->ability_count == 0) {
207 add_ability(character, character->base_attack);
208 }
209
210 character->equipment[slot] = NULL;
211 } else {
212 log_msg(WARNING, "Character", "No gear equipped in slot %d!", slot);
213 }
214}
215
216bool add_equipped_gear(character_t* character, gear_t* gear) {
217 NULL_PTR_HANDLER_RETURN(character, false, "Character", "In add_equipped_gear character is NULL");
218 NULL_PTR_HANDLER_RETURN(gear, false, "Character", "In add_equipped_gear gear is NULL");
219
220 if (gear->slot < MAX_SLOT) {
221 if (character->equipment[gear->slot] != NULL) {
222 log_msg(WARNING, "Character", "Slot %d is already occupied!", gear->slot);
223 return false;
224 }
225
226 character->equipment[gear->slot] = gear;
227 if (character->abilities[0] == character->base_attack) {
228 remove_ability(character, character->abilities[0]);
229 }
230
231 for (int i = 0; i < gear->num_abilities; ++i) {
232 add_ability(character, gear->abilities[i]);
233 }
234
235 return true;
236 }
237
238 log_msg(WARNING, "Character", "Invalid slot for gear %s!", gear->local_key);
239 return false;
240}
241
242void add_potion(character_t* character, potion_t* potion) {
243 NULL_PTR_HANDLER_RETURN(character, , "Character", "In add_potion character is NULL");
244 NULL_PTR_HANDLER_RETURN(potion, , "Character", "In add_potion potion is NULL");
245
246 if (character->potion_count < MAX_POTION_LIMIT) {
247 character->potion_inventory[character->potion_count] = potion;
248 character->potion_count++;
249 } else {
250 log_msg(WARNING, "Character", "%s cannot carry more potions!", character->name);
251 }
252}
253
254void remove_potion(character_t* character, potion_t* potion) {
255 NULL_PTR_HANDLER_RETURN(character, , "Character", "In remove_potion character is NULL");
256 NULL_PTR_HANDLER_RETURN(potion, , "Character", "In remove_potion potion is NULL");
257
258 for (int i = 0; i < character->potion_count; i++) {
259 if (character->potion_inventory[i] == potion) {
260 for (int j = i; j < character->potion_count - 1; j++) {
261 character->potion_inventory[j] = character->potion_inventory[j + 1];
262 }
263 character->potion_inventory[character->potion_count - 1] = NULL;
264 character->potion_count--;
265 return;
266 }
267 }
268 log_msg(WARNING, "Character", "Potion %s not found in inventory!", potion->name);
269}
270
271
272void equip_gear(character_t* character, gear_t* gear) {
273 NULL_PTR_HANDLER_RETURN(character, , "Character", "In equip_gear character is NULL");
274 NULL_PTR_HANDLER_RETURN(gear, , "Character", "In equip_gear gear is NULL");
275
276 if (add_equipped_gear(character, gear)) {
277 remove_gear(character, gear);
278
279 character->base_stats.strength += gear->stats.strength;
280 character->base_stats.intelligence += gear->stats.intelligence;
281 character->base_stats.dexterity += gear->stats.dexterity;
282 character->base_stats.constitution += gear->stats.constitution;
283 character->defenses.armor += gear->defenses.armor;
284 character->defenses.magic_resist += gear->defenses.magic_resist;
285 update_character_resources(&character->current_resources, &character->max_resources, &character->base_stats);
286
287 } else {
288 log_msg(WARNING, "Character", "Invalid slot for gear %s!", gear->local_key);
289 }
290}
291
292void unequip_gear(character_t* character, const gear_slot_t slot) {
293 NULL_PTR_HANDLER_RETURN(character, , "Character", "In unequip_gear character is NULL");
294 CHECK_ARG_RETURN(slot < 0 && slot >= MAX_SLOT, , "Character", "In unequip_gear slot is invalid: %d", slot);
295
296 add_gear(character, character->equipment[slot]);
297 remove_equipped_gear(character, slot);
298}
299
300void set_initial_xp(character_t* character, int xp) {
301 NULL_PTR_HANDLER_RETURN(character, , "Character", "In set_initial_xp character is NULL");
302 character->xp = xp;
303}
304
305void set_level(character_t* character, int level) {
306 NULL_PTR_HANDLER_RETURN(character, , "Character", "In set_level character is NULL");
307 character->level = level;
308}
309
310void set_xp_reward(character_t* character, int xp_reward) {
311 NULL_PTR_HANDLER_RETURN(character, , "Character", "In set_xp_reward character is NULL");
312 character->xp_reward = xp_reward;
313}
314
315void set_skill_points(character_t* character, int skill_points) {
316 NULL_PTR_HANDLER_RETURN(character, , "Character", "In set_skill_points character is NULL");
317 character->skill_points = skill_points;
318}
319
321 if (player == NULL) return;
322
323 // reset current stats to their starting values
324 player->current_resources.health = player->max_resources.health;
325 player->current_resources.mana = player->max_resources.mana;
326 player->current_resources.stamina = player->max_resources.stamina;
327}
Exposes functions for working with abilities.
void add_gear(character_t *character, gear_t *gear)
Adds gear to a character's inventory.
Definition character.c:156
void equip_gear(character_t *character, gear_t *gear)
Equips a gear item to a character.
Definition character.c:272
void update_character_resources(resources_t *current_resources, resources_t *max_resources, stats_t *base_stats)
Updates the character's resources based on their stats.
Definition character.c:86
void set_character_stats(character_t *character, int strength, int intelligence, int dexterity, int constitution)
Sets the stats for a character.
Definition character.c:66
void set_stats(stats_t *stats, int strength, int intelligence, int dexterity, int constitution)
Sets the stats for a character.
Definition character.c:77
void add_potion(character_t *character, potion_t *potion)
Adds a potion to a character's inventory.
Definition character.c:242
character_t * init_character(memory_pool_t *memory_pool, const character_type_t type, const char *name)
Initializes a new character.
Definition character.c:13
bool add_equipped_gear(character_t *character, gear_t *gear)
Adds an equipped gear in a specific slot of a character without updating stats and abilities.
Definition character.c:216
void free_character(memory_pool_t *memory_pool, character_t *character)
Frees the memory allocated for a character.
Definition character.c:60
void set_character_dmg_modifier(character_t *character, damage_type_t type, int value)
Sets the damage modifier for a character.
Definition character.c:115
void reset_player_stats(character_t *player)
Resets the player stats to their base values.
Definition character.c:320
void remove_gear(character_t *character, gear_t *gear)
Removes a gear item from a character's inventory.
Definition character.c:169
void remove_potion(character_t *character, potion_t *potion)
Removes a potion from a character's inventory.
Definition character.c:254
void set_skill_points(character_t *character, int skill_points)
Sets the skill points for a character.
Definition character.c:315
void remove_equipped_gear(character_t *character, gear_slot_t slot)
Removes the gear equipped in a specific slot of a character.
Definition character.c:187
void add_ability(character_t *character, ability_t *ability)
Adds an ability to a character.
Definition character.c:127
void set_xp_reward(character_t *character, int xp_reward)
Sets the XP reward for a character.
Definition character.c:310
void remove_ability(character_t *character, const ability_t *ability)
Removes an ability from a character.
Definition character.c:139
void set_level(character_t *character, int level)
Sets the level for a character.
Definition character.c:305
void set_initial_xp(character_t *character, int xp)
sets initial xp for a character
Definition character.c:300
void unequip_gear(character_t *character, const gear_slot_t slot)
Unequips a gear item from a character and adds it to the character's inventory.
Definition character.c:292
Exposes functions for working working with the character.
Defines common macros, types, and global variables for color schemes and utilities.
void log_msg(const log_level_t level, const char *module, const char *format,...)
Logs a formatted message with a specified log level and module.
Definition logger.c:246
Header file for logging functionality of the game.
void * memory_pool_alloc(memory_pool_t *pool, size_t size)
Allocates memory on the given memory pool.
void memory_pool_free(memory_pool_t *pool, void *ptr)
Sets the given data pointer to not active in the given memory pool.
Definition gear.h:32