1 /*
2  * weapons.h
3  * Copyright (C) 2009-2018 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 #ifndef __WEAPONS_H_
20 #define __WEAPONS_H_
21 
22 #include "items.h"
23 
24 typedef enum _ammo_class
25 {
26     AMMO_SLING,
27     AMMO_BOW,
28     AMMO_CROSSBOW,
29     AMMO_MAX
30 } ammo_class;
31 
32 typedef enum _ammo_t
33 {
34     AMT_STONE,
35     AMT_SBULLET,
36     AMT_ARROW,
37     AMT_BOLT,
38     AMT_MAX
39 } ammo_t;
40 
41 typedef struct _ammo_data
42 {
43     ammo_t type;
44     const char *name;
45     ammo_class ac;
46     int damage;
47     int accuracy;
48     int material;
49     int weight;
50     int price;
51     unsigned
52     obtainable: 1;
53 } ammo_data;
54 
55 typedef enum _weapon_class
56 {
57     WC_MELEE,   /* melee weapon */
58     WC_RANGED,  /* ranged weapon */
59     WC_MAX
60 } weapon_class;
61 
62 typedef enum _weapon_t
63 {
64     WT_ODAGGER,
65     WT_DAGGER,
66     WT_SLING,
67     WT_OSHORTSWORD,
68     WT_SHORTSWORD,
69     WT_ESHORTSWORD,
70     WT_OSPEAR,
71     WT_SPEAR,
72     WT_ESPEAR,
73     WT_BOW,
74     WT_CLUB,
75     WT_MACE,
76     WT_FLAIL,
77     WT_BATTLEAXE,
78     WT_CROSSBOW,
79     WT_LONGSWORD,
80     WT_2SWORD,
81     WT_SWORDSLASHING,
82     WT_LANCEOFDEATH,
83     WT_VORPALBLADE,
84     WT_SLAYER,
85     WT_SUNSWORD,
86     WT_BESSMAN,
87     WT_MAX
88 } weapon_t;
89 
90 typedef struct _weapon_data
91 {
92     weapon_t type;
93     const char *name;
94     const char *short_name;
95     weapon_class wc;    /* weapon class */
96     ammo_class ammo;    /* required class of ammunition for ranged weapons */
97     int damage;         /* weapon's base damage */
98     int accuracy;       /* weapon accuracy */
99     int material;       /* material type from item_materials */
100     int weight;         /* used to determine inventory weight and if item can be thrown */
101     int price;          /* base price in the shops */
102     unsigned
103         twohanded: 1,   /* needs two hands */
104         unique: 1,      /* unique */
105         article: 1,     /* needs an article in the description */
106         obtainable: 1,  /* available in the shop */
107         throwable: 1;   /* can be thrown */
108 } weapon_data;
109 
110 /* forward declarations */
111 struct player;
112 struct _monster;
113 
114 /* external vars */
115 extern const ammo_data ammos[AMT_MAX];
116 extern const char *ammo_class_name[AMMO_MAX];
117 extern const weapon_data weapons[WT_MAX];
118 
119 /* functions */
120 int weapon_calc_to_hit(struct player *p, struct _monster *m, item *weapon, item *ammo);
121 int  weapon_fire(struct player *p);
122 void weapon_swap(struct player *p);
123 
124 /*
125  * @brief Return a shortened description of a given weapon
126  *
127  * @param a weapon
128  * @return a newly allocated string that must be g_free()'d
129  */
130 char *weapon_shortdesc(item *weapon, guint available_space);
131 
ammo_base_damage(item * ammo)132 static inline int ammo_base_damage(item *ammo)
133 {
134     g_assert(ammo->id < WT_MAX);
135     return ammos[ammo->id].damage;
136 }
137 
ammo_damage(item * ammo)138 static inline int ammo_damage(item *ammo)
139 {
140     int dmg = ammo_base_damage(ammo)
141               + item_condition_bonus(ammo);
142 
143     /* even the worst ammo will not heal monsters */
144     return max(0, dmg);
145 }
146 
ammo_base_accuracy(item * ammo)147 static inline int ammo_base_accuracy(item *ammo)
148 {
149     g_assert(ammo->id < WT_MAX);
150     return ammos[ammo->id].accuracy;
151 }
152 
ammo_accuracy(item * ammo)153 static inline int ammo_accuracy(item *ammo)
154 {
155     return ammo_base_accuracy(ammo) + item_condition_bonus(ammo);
156 }
157 
weapon_base_damage(item * weapon)158 static inline int weapon_base_damage(item *weapon)
159 {
160     g_assert(weapon->id < WT_MAX);
161     return weapons[weapon->id].damage;
162 }
163 
weapon_damage(item * weapon)164 static inline int weapon_damage(item *weapon)
165 {
166     int dmg = weapon_base_damage(weapon)
167               + item_condition_bonus(weapon);
168 
169     /* even the worst weapon will not heal monsters */
170     return max(1, dmg);
171 }
172 
weapon_base_acc(item * weapon)173 static inline int weapon_base_acc(item *weapon)
174 {
175     g_assert(weapon->id < WT_MAX);
176     return weapons[weapon->id].accuracy;
177 }
178 
weapon_acc(item * weapon)179 static inline int weapon_acc(item *weapon)
180 {
181     return weapon_base_acc(weapon) + item_condition_bonus(weapon);
182 }
183 
184 /* macros */
185 #define ammo_name(itm)          (ammos[(itm)->id].name)
186 #define ammo_class(itm)         (ammos[(itm)->id].ac)
187 #define ammo_material(itm)      (ammos[(itm)->id].material)
188 #define ammo_weight(itm)        (ammos[(itm)->id].weight)
189 #define ammo_price(itm)         (ammos[(itm)->id].price)
190 #define ammo_t_obtainable(atm)  (ammos[atm].obtainable)
191 
192 #define weapon_type_obtainable(id)   (weapons[id].obtainable)
193 #define weapon_name(weapon)          (weapons[(weapon)->id].name)
194 #define weapon_short_name(weapon)    (weapons[(weapon)->id].short_name)
195 #define weapon_class(weapon)         (weapons[(weapon)->id].wc)
196 #define weapon_ammo(weapon)          (weapons[(weapon)->id].ammo)
197 #define weapon_material(weapon)      (weapons[(weapon)->id].material)
198 #define weapon_weight(weapon)        (weapons[(weapon)->id].weight)
199 #define weapon_price(weapon)         (weapons[(weapon)->id].price)
200 #define weapon_is_twohanded(weapon)  (weapons[(weapon)->id].twohanded)
201 #define weapon_is_ranged(weapon)     (weapons[(weapon)->id].wc == WC_RANGED)
202 #define weapon_is_unique(weapon)     (weapons[(weapon)->id].unique)
203 #define weapon_is_throwable(weapon)  (weapons[(weapon)->id].throwable)
204 #define weapon_needs_article(weapon) (weapons[(weapon)->id].article)
205 
206 #endif
207