1 /* $Id$ */
2 /* File: lua_bind.c */
3
4 /* Purpose: various lua bindings */
5
6 /*
7 * Copyright (c) 2001 DarkGod
8 *
9 * This software may be copied and distributed for educational, research, and
10 * not for profit purposes provided that this copyright and statement are
11 * included in all such copies.
12 */
13
14 #include "angband.h"
15 #include "lua.h"
16 #include "lualib.h"
17 #include "lauxlib.h"
18 #include "tolua.h"
19
20 extern lua_State* L;
21
22 /* items */
23 static char *lua_item_tester_fct;
lua_item_tester(object_type * o_ptr)24 static bool lua_item_tester(object_type* o_ptr)
25 {
26 int oldtop = lua_gettop(L);
27 bool ret;
28
29 lua_getglobal(L, lua_item_tester_fct);
30 tolua_pushusertype(L, o_ptr, tolua_tag(L, "object_type"));
31 lua_call(L, 1, 1);
32 ret = lua_tonumber(L, -1);
33 lua_settop(L, oldtop);
34 return (ret);
35 }
36
lua_set_item_tester(int tval,char * fct)37 void lua_set_item_tester(int tval, char *fct)
38 {
39 if (tval)
40 {
41 item_tester_tval = tval;
42 }
43 else
44 {
45 lua_item_tester_fct = fct;
46 item_tester_hook = lua_item_tester;
47 }
48 }
49
50
51 /* Spell schools */
new_school(int i,cptr name,s16b skill)52 s16b new_school(int i, cptr name, s16b skill)
53 {
54 schools[i].name = string_make(name);
55 schools[i].skill = skill;
56 return (i);
57 }
58
new_spell(int i,cptr name)59 s16b new_spell(int i, cptr name)
60 {
61 school_spells[i].name = string_make(name);
62 school_spells[i].level = 0;
63 school_spells[i].level = 0;
64 return (i);
65 }
66
grab_spell_type(s16b num)67 spell_type *grab_spell_type(s16b num)
68 {
69 return (&school_spells[num]);
70 }
71
grab_school_type(s16b num)72 school_type *grab_school_type(s16b num)
73 {
74 return (&schools[num]);
75 }
76
77 /* Change this fct if I want to switch to learnable spells */
lua_get_level(int Ind,s32b s,s32b lvl,s32b max,s32b min,s32b bonus)78 s32b lua_get_level(int Ind, s32b s, s32b lvl, s32b max, s32b min, s32b bonus)
79 {
80 s32b tmp;
81
82 tmp = lvl - ((school_spells[s].skill_level - 1) * (SKILL_STEP / 10));
83 lvl = (tmp * (max * (SKILL_STEP / 10)) / (SKILL_MAX / 10)) / (SKILL_STEP / 10);
84 if (lvl < min) lvl = min;
85 else if (lvl > 0)
86 {
87 tmp += bonus;
88 lvl = (tmp * (max * (SKILL_STEP / 10)) / (SKILL_MAX / 10)) / (SKILL_STEP / 10);
89 if (school_spells[s].spell_power) {
90 lvl *= (100 + get_skill_scale(p_ptr, SKILL_SPELL, 40));
91 lvl /= 100;
92 }
93 }
94 return lvl;
95 }
96
97 /* adj_mag_stat? stat_ind?? pfft */
lua_spell_chance(int i,s32b chance,int level,int skill_level,int mana,int cur_mana,int stat)98 s32b lua_spell_chance(int i, s32b chance, int level, int skill_level, int mana, int cur_mana, int stat)
99 {
100 int minfail;
101
102 /* correct LUA overflow bug */
103 if (chance >= 156) chance -= 256;
104
105 /* Reduce failure rate by "effective" level adjustment */
106 chance -= 3 * (level - skill_level);
107
108 /* Reduce failure rate by INT/WIS adjustment */
109 chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[stat]] - 1);
110
111 /* Not enough mana to cast */
112 if (chance < 0) chance = 0;
113 #if 0 /* just confuses and casting without mana is disabled anyway */
114 if (mana > cur_mana) chance += 15 * (mana - cur_mana);
115 #endif
116 /* Extract the minimum failure rate */
117 minfail = adj_mag_fail[p_ptr->stat_ind[stat]];
118
119 #if 0 /* disabled for the time being */
120 /*
121 * Non mage characters never get too good
122 */
123 if (!(PRACE_FLAG(PR1_ZERO_FAIL)))
124 {
125 if (minfail < 5) minfail = 5;
126 }
127
128 /* Hack -- Priest prayer penalty for "edged" weapons -DGK */
129 if ((forbid_non_blessed()) && (p_ptr->icky_wield)) chance += 25;
130 #endif /* 0 */
131
132 /* Minimum failure rate */
133 if (chance < minfail) chance = minfail;
134
135 /* Stunning makes spells harder */
136 if (p_ptr->stun > 50) chance += 25;
137 else if (p_ptr->stun) chance += 15;
138
139 /* Always a 5 percent chance of working */
140 if (chance > 95) chance = 95;
141
142 /* Return the chance */
143 return (chance);
144 }
145
146 #if 0
147 /* Cave */
148 cave_type *lua_get_cave(int y, int x)
149 {
150 return (&(cave[y][x]));
151 }
152
153 void set_target(int y, int x)
154 {
155 target_who = -1;
156 target_col = x;
157 target_row = y;
158 }
159
160 /* Level gen */
161 void get_map_size(char *name, int *ysize, int *xsize)
162 {
163 *xsize = 0;
164 *ysize = 0;
165 init_flags = INIT_GET_SIZE;
166 process_dungeon_file_full = TRUE;
167 process_dungeon_file(name, ysize, xsize, cur_hgt, cur_wid, TRUE);
168 process_dungeon_file_full = FALSE;
169
170 }
171
172 void load_map(char *name, int *y, int *x)
173 {
174 /* Set the correct monster hook */
175 set_mon_num_hook();
176
177 /* Prepare allocation table */
178 get_mon_num_prep();
179
180 init_flags = INIT_CREATE_DUNGEON;
181 process_dungeon_file_full = TRUE;
182 process_dungeon_file(name, y, x, cur_hgt, cur_wid, TRUE);
183 process_dungeon_file_full = FALSE;
184 }
185
186 bool alloc_room(int by0, int bx0, int ysize, int xsize, int *y1, int *x1, int *y2, int *x2)
187 {
188 int xval, yval, x, y;
189
190 /* Try to allocate space for room. If fails, exit */
191 if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return FALSE;
192
193 /* Get corner values */
194 *y1 = yval - ysize / 2;
195 *x1 = xval - xsize / 2;
196 *y2 = yval + (ysize) / 2;
197 *x2 = xval + (xsize) / 2;
198
199 /* Place a full floor under the room */
200 for (y = *y1 - 1; y <= *y2 + 1; y++)
201 {
202 for (x = *x1 - 1; x <= *x2 + 1; x++)
203 {
204 cave_type *c_ptr = &cave[y][x];
205 cave_set_feat(y, x, floor_type[rand_int(100)]);
206 c_ptr->info |= (CAVE_ROOM);
207 c_ptr->info |= (CAVE_GLOW);
208 }
209 }
210 return TRUE;
211 }
212
213
214 /* Files */
215 void lua_print_hook(cptr str)
216 {
217 fprintf(hook_file, str);
218 }
219
220
221 /*
222 * Finds a good random bounty monster
223 * Im too lazy to write it in lua since the lua API for monsters is not very well yet
224 */
225
226 /*
227 * Hook for bounty monster selection.
228 */
229 static bool lua_mon_hook_bounty(int r_idx)
230 {
231 monster_race* r_ptr = &r_info[r_idx];
232
233
234 /* Reject uniques */
235 if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE);
236
237 /* Reject those who cannot leave anything */
238 if (!(r_ptr->flags9 & RF9_DROP_CORPSE)) return (FALSE);
239
240 /* Accept only monsters that can be generated */
241 if (r_ptr->flags9 & RF9_SPECIAL_GENE) return (FALSE);
242 if (r_ptr->flags9 & RF9_NEVER_GENE) return (FALSE);
243
244 /* Reject pets */
245 if (r_ptr->flags7 & RF7_PET) return (FALSE);
246
247 /* Reject friendly creatures */
248 if (r_ptr->flags7 & RF7_FRIENDLY) return (FALSE);
249
250 /* Accept only monsters that are not breeders */
251 if (r_ptr->flags4 & RF4_MULTIPLY) return (FALSE);
252
253 /* Forbid joke monsters */
254 if (r_ptr->flags8 & RF8_JOKEANGBAND) return (FALSE);
255
256 /* Accept only monsters that are not good */
257 if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
258
259 /* The rest are acceptable */
260 return (TRUE);
261 }
262
263 int lua_get_new_bounty_monster(int lev)
264 {
265 int r_idx;
266
267 /*
268 * Set up the hooks -- no bounties on uniques or monsters
269 * with no corpses
270 */
271 get_mon_num_hook = lua_mon_hook_bounty;
272 get_mon_num_prep();
273
274 /* Set up the quest monster. */
275 r_idx = get_mon_num(lev);
276
277 /* Undo the filters */
278 get_mon_num_hook = NULL;
279 get_mon_num_prep();
280
281 return r_idx;
282 }
283
284 #endif
285
get_inven_sval(int Ind,int inven_slot)286 int get_inven_sval(int Ind, int inven_slot) {
287 return (inventory[inven_slot].sval);
288 }
get_inven_pval(int Ind,int inven_slot)289 int get_inven_pval(int Ind, int inven_slot) {
290 return (inventory[inven_slot].pval);
291 }
get_inven_xtra(int Ind,int inven_slot,int n)292 int get_inven_xtra(int Ind, int inven_slot, int n) {
293 /* browsing item in a store? */
294 if (inven_slot < 0) {
295 switch (n) {
296 case 1: return (store.stock[(-inven_slot) - 1].xtra1);
297 case 2: return (store.stock[(-inven_slot) - 1].xtra2);
298 case 3: return (store.stock[(-inven_slot) - 1].xtra3);
299 case 4: return (store.stock[(-inven_slot) - 1].xtra4);
300 case 5: return (store.stock[(-inven_slot) - 1].xtra5);
301 case 6: return (store.stock[(-inven_slot) - 1].xtra6);
302 case 7: return (store.stock[(-inven_slot) - 1].xtra7);
303 case 8: return (store.stock[(-inven_slot) - 1].xtra8);
304 case 9: return (store.stock[(-inven_slot) - 1].xtra9);
305 default: return (0); //failure
306 }
307 } else { /* browsing item in inventory */
308 switch (n) {
309 case 1: return (inventory[inven_slot].xtra1);
310 case 2: return (inventory[inven_slot].xtra2);
311 case 3: return (inventory[inven_slot].xtra3);
312 case 4: return (inventory[inven_slot].xtra4);
313 case 5: return (inventory[inven_slot].xtra5);
314 case 6: return (inventory[inven_slot].xtra6);
315 case 7: return (inventory[inven_slot].xtra7);
316 case 8: return (inventory[inven_slot].xtra8);
317 case 9: return (inventory[inven_slot].xtra9);
318 default: return (0); //failure
319 }
320 }
321 }
322
323 /* lua wrapper for c_get_item that feeds the arguments to c_get_item correctly */
get_item_aux(int * cp,cptr pmt,bool equip,bool inven,bool floor)324 bool get_item_aux(int *cp, cptr pmt, bool equip, bool inven, bool floor) {
325 int mode = 0;
326
327 if (equip) mode |= USE_EQUIP;
328 if (inven) mode |= USE_INVEN;
329 if (floor) mode |= USE_FLOOR;
330
331 return c_get_item(cp, pmt, mode);
332 }
333