1 /*
2 * effects.c
3 * Copyright (C) 2009-2020 Joachim de Groot <jdegroot@web.de>
4 *
5 * NLarn is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * NLarn is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <glib.h>
20 #include <string.h>
21
22 #include "cJSON.h"
23 #include "effects.h"
24 #include "game.h"
25 #include "extdefs.h"
26 #include "random.h"
27
28 static const effect_data effects[ET_MAX] =
29 {
30 /*
31 name "name" duration amount desc
32 msg_start
33 msg_stop
34 msg_start_monster
35 msg_stop_monster
36 var_duration var_amount inc_duration inc_amount
37 */
38
39 {
40 ET_NONE, "ET_NONE", 0, 0, NULL,
41 NULL, NULL, NULL, NULL,
42 FALSE, FALSE, FALSE, FALSE
43 },
44
45 {
46 ET_INC_CON, "ET_INC_CON", 1, 1, NULL,
47 "You have a greater intestinal constitution!",
48 NULL, NULL, NULL,
49 FALSE, FALSE, FALSE, TRUE
50 },
51
52 {
53 ET_INC_DEX, "ET_INC_DEX", 1, 1, NULL,
54 "You feel skilful!",
55 "Your dextrousness returns to normal.",
56 NULL, NULL,
57 FALSE, FALSE, FALSE, TRUE
58 },
59
60 {
61 ET_INC_INT, "ET_INC_INT", 1, 1, NULL,
62 "You feel clever!",
63 "You are not so smart anymore.",
64 NULL, NULL,
65 FALSE, FALSE, FALSE, TRUE
66 },
67
68 {
69 ET_INC_STR, "ET_INC_STR", 1, 1, NULL,
70 "Your muscles are stronger!",
71 "Your strength returns to normal.",
72 NULL, NULL,
73 FALSE, FALSE, FALSE, TRUE
74 },
75
76 {
77 ET_INC_WIS, "ET_INC_WIS", 1, 1, NULL,
78 "You feel more self-confident!",
79 NULL, NULL, NULL,
80 FALSE, FALSE, FALSE, TRUE
81 },
82
83 {
84 ET_INC_RND, "ET_INC_RND", 1, 1, NULL,
85 NULL, NULL, NULL, NULL,
86 FALSE, FALSE, FALSE, FALSE
87 },
88
89 {
90 ET_INC_DAMAGE, "ET_INC_DAMAGE", 100, 10, NULL,
91 NULL, NULL, NULL, NULL,
92 TRUE, TRUE, FALSE, TRUE
93 },
94
95 {
96 ET_INC_HP_MAX, "ET_INC_HP_MAX", 1, 5 /* % */, NULL,
97 "You feel healthy!",
98 NULL, NULL, NULL,
99 FALSE, FALSE, FALSE, FALSE
100 },
101
102 {
103 ET_INC_MP_MAX, "ET_INC_MP_MAX", 1, 5 /* % */, NULL,
104 "You feel energetic!",
105 NULL, NULL, NULL,
106 FALSE, FALSE, FALSE, FALSE
107 },
108
109 {
110 ET_INC_HP_REGEN, "ET_INC_HP_REGEN", 0, 1, NULL,
111 NULL, NULL, NULL, NULL,
112 FALSE, FALSE, FALSE, FALSE
113 },
114
115 {
116 ET_INC_MP_REGEN, "ET_INC_MP_REGEN", 0, 1, NULL,
117 NULL, NULL, NULL, NULL,
118 FALSE, FALSE, FALSE, FALSE
119 },
120
121 {
122 ET_INC_LEVEL, "ET_INC_LEVEL", 1, 1, NULL,
123 "You feel much more skilful!",
124 NULL, NULL, NULL,
125 FALSE, FALSE, FALSE, FALSE
126 },
127
128 {
129 ET_INC_EXP, "ET_INC_EXP", 1, 0, NULL,
130 "You feel experienced.",
131 NULL, NULL, NULL,
132 FALSE, FALSE, FALSE, FALSE
133 },
134
135 {
136 ET_RESIST_FIRE, "ET_RESIST_FIRE", 0, 25, NULL,
137 "You feel a chill run up your spine!",
138 NULL, NULL, NULL,
139 FALSE, FALSE, FALSE, TRUE
140 },
141
142 {
143 ET_RESIST_COLD, "ET_RESIST_COLD", 0, 25, NULL,
144 NULL, NULL, NULL, NULL,
145 FALSE, FALSE, FALSE, TRUE
146 },
147
148 {
149 ET_RESIST_MAGIC, "ET_RESIST_MAGIC", 0, 25, NULL,
150 NULL, NULL, NULL, NULL,
151 FALSE, FALSE, FALSE, TRUE
152 },
153
154 {
155 ET_PROTECTION, "ET_PROTECTION", 250, 3, "protected",
156 "You feel protected!", "Your protection wanes.",
157 NULL, NULL,
158 TRUE, FALSE, TRUE, FALSE
159 },
160
161 {
162 ET_STEALTH, "ET_STEALTH", 250, TRUE, "stealthy",
163 "You start to move stealthily.",
164 "You're not stealthy anymore.",
165 NULL, NULL,
166 TRUE, FALSE, TRUE, FALSE
167 },
168
169 {
170 ET_AWARENESS, "ET_AWARENESS", 250, 3, "aware",
171 "You become aware of your surroundings.",
172 "You are no longer aware of your surroundings.",
173 NULL, NULL,
174 TRUE, FALSE, TRUE, FALSE
175 },
176
177 {
178 ET_SPEED, "ET_SPEED", 250, 25, "fast",
179 "You are suddenly moving much faster.",
180 "You feel yourself slow down.",
181 "The %s seems to move much faster.",
182 "The %s suddenly slows down.",
183 TRUE, FALSE, FALSE, TRUE
184 },
185
186 {
187 ET_HEROISM, "ET_HEROISM", 250, 5, NULL,
188 "WOW!!! You feel Super-fantastic!!!",
189 "You return to normal. How sad!",
190 "The %s looks more perilous!",
191 "The %s looks less perilous.",
192 FALSE, FALSE, FALSE, FALSE
193 },
194
195 {
196 ET_INVISIBILITY, "ET_INVISIBILITY", 250, TRUE, "invisible",
197 "Suddenly you can't see yourself!",
198 "You are no longer invisible.",
199 "The %s disappears.",
200 NULL,
201 TRUE, FALSE, TRUE, FALSE
202 },
203
204 {
205 ET_INVULNERABILITY, "ET_INVULNERABILITY", 250, 10, "invulnerable",
206 NULL, NULL, NULL, NULL,
207 TRUE, FALSE, TRUE, FALSE
208 },
209
210 {
211 ET_INFRAVISION, "ET_INFRAVISION", 250, TRUE, "infravision",
212 "Your vision sharpens.",
213 "Your vision returns to normal.",
214 "The %s seems more observant.",
215 "The %s seems less observant.",
216 TRUE, FALSE, TRUE, FALSE
217 },
218
219 {
220 ET_ENLIGHTENMENT, "ET_ENLIGHTENMENT", 250, 8, "enlightened",
221 "You have been granted enlightenment!",
222 "You are no longer enlightened.",
223 NULL, NULL,
224 TRUE, FALSE, TRUE, FALSE
225 },
226
227 {
228 ET_REFLECTION, "ET_REFLECTION", 400, TRUE, "reflection",
229 NULL, NULL, NULL, NULL,
230 TRUE, FALSE, TRUE, FALSE
231 },
232
233 {
234 ET_DETECT_MONSTER, "ET_DETECT_MONSTER", 10, TRUE, NULL,
235 "You sense the presence of monsters.",
236 NULL, NULL, NULL,
237 FALSE, FALSE, TRUE, FALSE
238 },
239
240 {
241 ET_HOLD_MONSTER, "ET_HOLD_MONSTER", 30, TRUE, "held",
242 NULL, NULL,
243 "The %s seems to freeze.",
244 "The %s can move again.",
245 TRUE, FALSE, FALSE, FALSE
246 },
247
248 {
249 ET_SCARED, "ET_SCARED", 250, TRUE, "scared",
250 NULL, NULL,
251 "The %s is very afraid.",
252 "The %s is no longer scared.",
253 TRUE, FALSE, TRUE, FALSE
254 },
255
256 {
257 ET_CHARM_MONSTER, "ET_CHARM_MONSTER", 50, TRUE, "charmed",
258 NULL, NULL,
259 "The %s is awestruck at your magnificence!",
260 "The %s is no longer impressed.",
261 TRUE, FALSE, TRUE, FALSE
262 },
263
264 {
265 ET_INC_HP, "ET_INC_HP", 1, 20 /* % */, NULL,
266 "You feel better.",
267 NULL,
268 "The %s looks better.",
269 NULL,
270 FALSE, TRUE, FALSE, FALSE
271 },
272
273 {
274 ET_MAX_HP, "ET_MAX_HP", 1, 100 /* % */, NULL,
275 "You are completely healed.",
276 NULL,
277 "The %s looks completely healed.",
278 NULL,
279 FALSE, FALSE, FALSE, FALSE
280 },
281
282 {
283 ET_INC_MP, "ET_INC_MP", 1, 20 /* % */, NULL,
284 "Magical energies course through your body.",
285 NULL,
286 "The %s seems to regain energy.",
287 NULL,
288 FALSE, TRUE, FALSE, FALSE
289 },
290
291 {
292 ET_MAX_MP, "ET_MAX_MP", 1, 100 /* % */, NULL,
293 "You feel much more powerful.",
294 NULL,
295 "The %s looks much more powerful.",
296 NULL,
297 FALSE, FALSE, FALSE, FALSE
298 },
299
300 {
301 ET_CANCELLATION, "ET_CANCELLATION", 250, TRUE, "cancellation",
302 NULL, NULL, NULL, NULL,
303 TRUE, FALSE, TRUE, FALSE
304 },
305
306 {
307 ET_UNDEAD_PROTECTION, "ET_UNDEAD_PROTECTION", 400, TRUE, "undead protection",
308 "You feel safe in the dark.",
309 NULL, NULL, NULL,
310 TRUE, FALSE, TRUE, FALSE
311 },
312
313 {
314 ET_SPIRIT_PROTECTION, "ET_SPIRIT_PROTECTION", 400, TRUE, "spirit protection",
315 "You feel a protecting force.",
316 NULL, NULL, NULL,
317 TRUE, FALSE, TRUE, FALSE
318 },
319
320 {
321 ET_LIFE_PROTECTION, "ET_LIFE_PROTECTION", 2500, TRUE, "life protection",
322 "You've never felt so safe.",
323 "You feel less safe than before.",
324 NULL, NULL,
325 FALSE, FALSE, FALSE, FALSE
326 },
327
328 {
329 ET_NOTHEFT, "ET_NOTHEFT", 400, TRUE, "theft protection",
330 NULL, NULL, NULL, NULL,
331 TRUE, FALSE, TRUE, FALSE
332 },
333
334 {
335 ET_SUSTAINMENT, "ET_SUSTAINMENT", 400, TRUE, "sustainment",
336 NULL, NULL, NULL, NULL,
337 TRUE, FALSE, TRUE, FALSE
338 },
339
340 {
341 ET_TIMESTOP, "ET_TIMESTOP", 20, TRUE, "time stop",
342 NULL, NULL, NULL, NULL,
343 TRUE, FALSE, TRUE, FALSE
344 },
345
346 {
347 ET_WALL_WALK, "ET_WALL_WALK", 20, TRUE, "wall-walk",
348 "You can now walk through walls.",
349 "You can no longer walk through walls.",
350 NULL, NULL,
351 TRUE, FALSE, TRUE, FALSE
352 },
353
354 {
355 ET_LEVITATION, "ET_LEVITATION", 20, TRUE, "levitation",
356 "You start to float in the air!",
357 "You gently sink to the ground.",
358 "The %s starts to float in the air!",
359 "The %s gently sinks to the ground.",
360 TRUE, FALSE, TRUE, FALSE
361 },
362
363 {
364 ET_DEC_CON, "ET_DEC_CON", 1, 1, NULL,
365 "You feel incapacitated.",
366 "You feel tougher.",
367 NULL, NULL,
368 FALSE, FALSE, TRUE, TRUE
369 },
370
371 {
372 ET_DEC_DEX, "ET_DEC_DEX", 1, 1, NULL,
373 "You feel clumsy.",
374 "Your dexterousness returns.",
375 NULL, NULL,
376 FALSE, FALSE, TRUE, TRUE
377 },
378
379 {
380 ET_DEC_INT, "ET_DEC_INT", 1, 1, NULL,
381 "You feel imbecile.",
382 "Your intelligence returns.",
383 NULL, NULL,
384 FALSE, FALSE, TRUE, TRUE
385 },
386
387 {
388 ET_DEC_STR, "ET_DEC_STR", 1, 1, NULL,
389 "You are weaker.",
390 "You regain your strength.",
391 NULL, NULL,
392 FALSE, FALSE, TRUE, TRUE
393 },
394
395 {
396 ET_DEC_WIS, "ET_DEC_WIS", 1, 1, NULL,
397 "You feel ignorant.",
398 "You feel less ignorant.",
399 NULL, NULL,
400 FALSE, FALSE, TRUE, TRUE
401 },
402
403 {
404 ET_DEC_RND, "ET_DEC_RND", 1, 1, NULL,
405 NULL, NULL, NULL, NULL,
406 FALSE, FALSE, FALSE, FALSE
407 },
408
409 {
410 ET_AGGRAVATE_MONSTER, "ET_AGGRAVATE_MONSTER", 500, TRUE, "aggravating",
411 "You sense rising anger.",
412 NULL, NULL, NULL,
413 TRUE, FALSE, TRUE, FALSE
414 },
415
416 {
417 ET_SLEEP, "ET_SLEEP", 25, TRUE, "sleeping",
418 "You fall asleep.",
419 "You wake up.",
420 "The %s falls asleep.",
421 "The %s wakes up.",
422 TRUE, FALSE, FALSE, FALSE
423 },
424
425 {
426 ET_DIZZINESS, "ET_DIZZINESS", 250, 5, "dizzy",
427 "You're dizzy and weak!",
428 "You're no longer dizzy.",
429 "The %s looks dizzy and weak.",
430 "The %s no longer looks dizzy.",
431 TRUE, FALSE, FALSE, FALSE
432 },
433
434 {
435 ET_SICKNESS, "ET_SICKNESS", 250, 10, "sick",
436 "You feel a sickness coming on.",
437 "You now feel better.",
438 NULL, NULL,
439 TRUE, TRUE, TRUE, TRUE
440 },
441
442 {
443 ET_BLINDNESS, "ET_BLINDNESS", 250, TRUE, "blind",
444 "You can't see anything!",
445 "The blindness lifts.",
446 "The %s seems to be blinded.",
447 "Looks like the %s can see again.",
448 TRUE, FALSE, FALSE, FALSE
449 },
450
451 {
452 ET_CLUMSINESS, "ET_CLUMSINESS", 250, TRUE, "clumsy",
453 "You begin to lose hand to eye coordination!",
454 "You're less awkward now.",
455 NULL, NULL,
456 TRUE, FALSE, FALSE, FALSE
457 },
458
459 {
460 ET_ITCHING, "ET_ITCHING", 100, TRUE, "itching",
461 "You feel an irritation spread over your skin!",
462 "The irritation subsides.",
463 NULL, NULL,
464 TRUE, FALSE, FALSE, FALSE
465 },
466
467 {
468 ET_CONFUSION, "ET_CONFUSION", 25, TRUE, "confused",
469 "You are confused.",
470 "You regain your senses.",
471 "The %s looks confused.",
472 "The %s seems to have regained it's senses.",
473 TRUE, FALSE, FALSE, FALSE
474 },
475
476 {
477 ET_PARALYSIS, "ET_PARALYSIS", 25, TRUE, "paralysed",
478 "You are paralysed.",
479 "You can move again.",
480 NULL, NULL,
481 TRUE, FALSE, FALSE, FALSE
482 },
483
484 {
485 ET_POISON, "ET_POISON", 300, 1, "poisoned",
486 NULL, /* message is shown in player_damage_take */
487 "You are cured.",
488 "The %s looks poisoned.",
489 "The %s looks cured.",
490 TRUE, FALSE, TRUE, TRUE
491 },
492
493 {
494 ET_AMNESIA, "ET_AMNESIA", 1, 0, NULL,
495 NULL, NULL, NULL, NULL,
496 FALSE, FALSE, FALSE, FALSE
497 },
498
499 {
500 ET_SLOWNESS, "ET_SLOWNESS", 250, 25, "slow",
501 "You feel yourself slow down.",
502 "You are moving faster again.",
503 "The %s slows down.",
504 "The %s seems to move much faster.",
505 TRUE, FALSE, FALSE, TRUE
506 },
507
508 {
509 ET_BURDENED, "ET_BURDENED", 0, 25, "burdened",
510 "You are burdened.",
511 "You are no longer burdened.",
512 NULL, NULL,
513 FALSE, FALSE, FALSE, FALSE
514 },
515
516 {
517 ET_OVERSTRAINED, "ET_OVERSTRAINED", 0, TRUE, "overload",
518 "You are overloaded!",
519 "You are no longer overloaded.",
520 NULL, NULL,
521 FALSE, FALSE, FALSE, FALSE
522 },
523
524 {
525 ET_TRAPPED, "ET_TRAPPED", 10, TRUE, "trapped",
526 NULL,
527 "You are no longer trapped!",
528 NULL,
529 "The %s climbs out of the pit!",
530 TRUE, FALSE, TRUE, FALSE
531 },
532 };
533
effect_new(effect_t type)534 effect *effect_new(effect_t type)
535 {
536 effect *ne;
537
538 g_assert(type > ET_NONE && type < ET_MAX);
539
540 ne = g_malloc0(sizeof(effect));
541 ne->type = type;
542 ne->start = game_turn(nlarn);
543
544 /* determine effect duration */
545 if (effects[type].var_duration)
546 {
547 ne->turns = divert(effects[type].duration, 10);
548 }
549 else
550 {
551 ne->turns = effects[type].duration;
552 }
553
554 /* determine effect amount */
555 if (effects[type].var_amount)
556 {
557 ne->amount = divert(effects[type].amount, 10);
558 }
559 else
560 {
561 ne->amount = effects[type].amount;
562 }
563
564 /* register effect */
565 ne->oid = game_effect_register(nlarn, ne);
566
567 return ne;
568 }
569
effect_copy(effect * e)570 effect *effect_copy(effect *e)
571 {
572 effect *ne;
573
574 g_assert(e != NULL);
575
576 ne = g_malloc(sizeof(effect));
577 memcpy(ne, e, sizeof(effect));
578
579 /* register copy with game */
580 ne->oid = game_effect_register(nlarn, ne);
581
582 return ne;
583 }
584
effect_destroy(effect * e)585 void effect_destroy(effect *e)
586 {
587 g_assert(e != NULL);
588
589 /* unregister effect */
590 game_effect_unregister(nlarn, e->oid);
591
592 g_free(e);
593 }
594
effect_serialize(gpointer oid,effect * e,cJSON * root)595 void effect_serialize(gpointer oid, effect *e, cJSON *root)
596 {
597 cJSON *eval;
598
599 cJSON_AddItemToArray(root, eval = cJSON_CreateObject());
600
601 cJSON_AddNumberToObject(eval,"oid", GPOINTER_TO_UINT(oid));
602 cJSON_AddNumberToObject(eval,"type", e->type);
603 cJSON_AddNumberToObject(eval,"start", e->start);
604 cJSON_AddNumberToObject(eval,"turns", e->turns);
605 cJSON_AddNumberToObject(eval,"amount", e->amount);
606
607 if (e->item)
608 {
609 cJSON_AddNumberToObject(eval,"item", GPOINTER_TO_UINT(e->item));
610 }
611 }
612
effect_deserialize(cJSON * eser,game * g)613 effect *effect_deserialize(cJSON *eser, game *g)
614 {
615 effect *e;
616 guint oid;
617 cJSON *itm;
618
619 e = g_malloc0(sizeof(effect));
620
621 oid = cJSON_GetObjectItem(eser, "oid")->valueint;
622 e->oid = GUINT_TO_POINTER(oid);
623
624 e->type = cJSON_GetObjectItem(eser, "type")->valueint;
625 e->start = cJSON_GetObjectItem(eser, "start")->valueint;
626 e->turns = cJSON_GetObjectItem(eser, "turns")->valueint;
627 e->amount = cJSON_GetObjectItem(eser, "amount")->valueint;
628
629 if ((itm = cJSON_GetObjectItem(eser, "item")))
630 {
631 e->item = GUINT_TO_POINTER(itm->valueint);
632 }
633
634 /* add effect to game */
635 g_hash_table_insert(g->effects, e->oid, e);
636
637 /* increase max_id to match used ids */
638 if (g->effect_max_id < oid)
639 {
640 g->effect_max_id = oid;
641 }
642
643 return e;
644 }
645
effects_serialize(GPtrArray * effs)646 cJSON *effects_serialize(GPtrArray *effs)
647 {
648 cJSON *eser = cJSON_CreateArray();
649
650 for (guint idx = 0; idx < effs->len; idx++)
651 {
652 gpointer eff_oid = g_ptr_array_index(effs, idx);
653 cJSON_AddItemToArray(eser, cJSON_CreateNumber(GPOINTER_TO_UINT(eff_oid)));
654 }
655
656 return eser;
657 }
658
effects_deserialize(cJSON * eser)659 GPtrArray *effects_deserialize(cJSON *eser)
660 {
661 GPtrArray *effs = g_ptr_array_new();
662
663 for (int idx = 0; idx < cJSON_GetArraySize(eser); idx++)
664 {
665 cJSON *effser = cJSON_GetArrayItem(eser, idx);
666 guint oid = effser->valueint;
667 g_ptr_array_add(effs, GUINT_TO_POINTER(oid));
668 }
669
670 return effs;
671 }
672
effect_type_name(effect_t type)673 const char *effect_type_name(effect_t type)
674 {
675 g_assert(type < ET_MAX);
676 return effects[type].name;
677 }
678
effect_type_amount(effect_t type)679 int effect_type_amount(effect_t type)
680 {
681 g_assert(type < ET_MAX);
682 return effects[type].amount;
683 }
684
effect_type_duration(effect_t type)685 guint effect_type_duration(effect_t type)
686 {
687 g_assert(type < ET_MAX);
688 return effects[type].duration;
689 }
690
effect_type_inc_duration(effect_t type)691 gboolean effect_type_inc_duration(effect_t type)
692 {
693 g_assert(type < ET_MAX);
694 return effects[type].inc_duration;
695 }
696
effect_type_inc_amount(effect_t type)697 gboolean effect_type_inc_amount(effect_t type)
698 {
699 g_assert(type < ET_MAX);
700 return effects[type].inc_amount;
701 }
702
effect_get_desc(effect * e)703 const char *effect_get_desc(effect *e)
704 {
705 g_assert(e != NULL && e->type > ET_NONE && e->type < ET_MAX);
706 return effects[e->type].desc;
707 }
708
effect_get_msg_start(effect * e)709 const char *effect_get_msg_start(effect *e)
710 {
711 g_assert(e != NULL && e->type > ET_NONE && e->type < ET_MAX);
712 return effects[e->type].msg_start;
713 }
714
effect_get_msg_stop(effect * e)715 const char *effect_get_msg_stop(effect *e)
716 {
717 g_assert(e != NULL && e->type > ET_NONE && e->type < ET_MAX);
718 return effects[e->type].msg_stop;
719 }
720
effect_get_msg_m_start(effect * e)721 const char *effect_get_msg_m_start(effect *e)
722 {
723 g_assert(e != NULL && e->type > ET_NONE && e->type < ET_MAX);
724 return effects[e->type].msg_start_monster;
725 }
726
effect_get_msg_m_stop(effect * e)727 const char *effect_get_msg_m_stop(effect *e)
728 {
729 g_assert(e != NULL && e->type > ET_NONE && e->type < ET_MAX);
730 return effects[e->type].msg_stop_monster;
731 }
732
effect_get_amount(effect * e)733 int effect_get_amount(effect *e)
734 {
735 g_assert (e != NULL);
736 return e->amount;
737 }
738
effect_add(GPtrArray * ea,effect * ne)739 effect *effect_add(GPtrArray *ea, effect *ne)
740 {
741 effect *e;
742
743 g_assert(ea != NULL && ne != NULL);
744
745 /* check for existing effects unless the effect belongs to an item */
746 if (!ne->item && (e = effect_get(ea, ne->type)))
747 {
748 gboolean modified_existing = FALSE;
749
750 /* if the effect's duration can be extended, reset it */
751 if (effects[e->type].inc_duration)
752 {
753 e->turns = max(e->turns, ne->turns);
754 modified_existing = TRUE;
755 }
756
757 /* if the effect's amount can be extended, do so */
758 if (effects[e->type].inc_amount)
759 {
760 e->amount += ne->amount;
761 modified_existing = TRUE;
762 }
763
764 effect_destroy(ne);
765
766 if (modified_existing == TRUE)
767 {
768 return e;
769 }
770 else
771 {
772 return NULL;
773 }
774 }
775 else
776 {
777 g_ptr_array_add(ea, ne->oid);
778 return ne;
779 }
780 }
781
effect_del(GPtrArray * ea,effect * e)782 int effect_del(GPtrArray *ea, effect *e)
783 {
784 g_assert(ea != NULL && e != NULL);
785 return g_ptr_array_remove_fast(ea, e->oid);
786 }
787
effect_get(GPtrArray * ea,effect_t type)788 effect *effect_get(GPtrArray *ea, effect_t type)
789 {
790 g_assert(ea != NULL && type > ET_NONE && type < ET_MAX);
791
792 for (guint idx = 0; idx < ea->len; idx++)
793 {
794 gpointer effect_id = g_ptr_array_index(ea, idx);
795 effect *e = game_effect_get(nlarn, effect_id);
796
797 /* do not return effects caused by items */
798 if ((e->type == type) && (e->item == NULL))
799 {
800 return e;
801 }
802 }
803
804 return NULL;
805 }
806
effect_query(GPtrArray * ea,effect_t type)807 int effect_query(GPtrArray *ea, effect_t type)
808 {
809 int amount = 0;
810
811 g_assert(ea != NULL && type > ET_NONE && type < ET_MAX);
812
813 for (guint idx = 0; idx < ea->len; idx++)
814 {
815 gpointer effect_id = g_ptr_array_index(ea, idx);
816 effect *e = game_effect_get(nlarn, effect_id);
817
818 if (e->type == type) amount += e->amount;
819 }
820
821 return amount;
822 }
823
effect_expire(effect * e)824 int effect_expire(effect *e)
825 {
826 g_assert(e != NULL);
827
828 if (e->turns > 1)
829 {
830 e->turns--;
831 }
832 else if (e->turns != 0)
833 {
834 e->turns = -1;
835 }
836
837 return e->turns;
838 }
839