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