File: shipwepselect.cpp

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (505 lines) | stat: -rw-r--r-- 15,265 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
#include "shipwepselect.h"
#include "ship/ship.h"
#include "weapon/weapon.h"
#include "missionui/missionweaponchoice.h"
#include "network/multiteamselect.h"

namespace scripting {
namespace api {

ss_wing_info_h::ss_wing_info_h() : ss_wing(-1) {}
ss_wing_info_h::ss_wing_info_h(int l_wing) : ss_wing(l_wing) {}
bool ss_wing_info_h::isValid() const
{
	return ss_wing >= 0;
}
ss_wing_info* ss_wing_info_h::getWing() const
{
	return &Ss_wings[ss_wing];
}

int ss_wing_info_h::getWingIndex() const
{
	return ss_wing;
}

ss_slot_info_h::ss_slot_info_h() {}
ss_slot_info_h::ss_slot_info_h(ss_slot_info* l_slots, int l_idx, int l_wing) : ss_slots(l_slots), ss_idx(l_idx), ss_wing(l_wing) {}
bool ss_slot_info_h::isValid() const
{
	return ss_slots != nullptr;
}
ss_slot_info* ss_slot_info_h::getSlot() const
{
	return &ss_slots[ss_idx];
}

int ss_slot_info_h::getSlotIndex() const
{
	return ss_idx;
}

int ss_slot_info_h::getWingIndex() const
{
	return ss_wing;
}

wss_unit_wep_h::wss_unit_wep_h() : ss_unit(-1) {}
wss_unit_wep_h::wss_unit_wep_h(int l_unit) : ss_unit(l_unit) {}
bool wss_unit_wep_h::isValid() const
{
	return ss_unit >= 0;
	// return ((ss_unit >= 0) && ((ss_bank >= 0) && (ss_bank <= 6)));
}
wss_unit* wss_unit_wep_h::getBank() const
{
	return &Wss_slots[ss_unit];
}

wss_unit_count_h::wss_unit_count_h() : ss_unit(-1) {}
wss_unit_count_h::wss_unit_count_h(int l_unit) : ss_unit(l_unit) {}
bool wss_unit_count_h::isValid() const
{
	return ss_unit >= 0;
	// return ((ss_unit >= 0) && ((ss_bank >= 0) && (ss_bank <= 6)));
}
wss_unit* wss_unit_count_h::getBank() const
{
	return &Wss_slots[ss_unit];
}

//**********HANDLE: loadout wing
ADE_OBJ(l_Loadout_Wing_Slot, ss_slot_info_h, "loadout_wing_slot", "Loadout wing slot handle");

ADE_VIRTVAR(isShipLocked, l_Loadout_Wing_Slot, nullptr, "If the slot's ship is locked", "boolean", "The slot ship status")
{
	ss_slot_info_h current;
	if (!ade_get_args(L, "o", l_Loadout_Wing_Slot.Get(&current))) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	return ade_set_args(L, "b", (current.getSlot()->status & WING_SLOT_SHIPS_DISABLED) != 0);
}

ADE_VIRTVAR(isWeaponLocked,
	l_Loadout_Wing_Slot,
	nullptr,
	"If the slot's weapons are locked",
	"boolean",
	"The slot weapon status")
{
	ss_slot_info_h current;
	if (!ade_get_args(L, "o", l_Loadout_Wing_Slot.Get(&current))) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	return ade_set_args(L, "b", (current.getSlot()->status & WING_SLOT_WEAPONS_DISABLED) != 0);
}

ADE_VIRTVAR(isDisabled, l_Loadout_Wing_Slot, nullptr, "If the slot is not used in the current mission or disabled for the current player in multi", "boolean", "The slot disabled status")
{
	ss_slot_info_h current;
	if (!ade_get_args(L, "o", l_Loadout_Wing_Slot.Get(&current))) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	bool result = !current.getSlot()->in_mission;
	if (Game_mode & GM_MULTIPLAYER) {
		int index = (current.getWingIndex() * MAX_WING_SLOTS) + current.getSlotIndex();
		result = multi_ts_disabled_slot(index);
	} 

	return ade_set_args(L, "b", result);
}

ADE_VIRTVAR(isFilled, l_Loadout_Wing_Slot, "boolean", "If the slot is empty or filled. true if filled, false if empty", "boolean", "The slot filled status")
{
	ss_slot_info_h current;
	bool setv;
	if (!ade_get_args(L, "o|b", l_Loadout_Wing_Slot.Get(&current), &setv)) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		if (Game_mode & GM_MULTIPLAYER) {
			LuaError(L, "This property may not be modified in multiplayer.");
			return ADE_RETURN_NIL;
		}
		if (!(current.getSlot()->status & WING_SLOT_DISABLED)) {
			if (setv) {
				current.getSlot()->status &= ~WING_SLOT_EMPTY;
				current.getSlot()->status |= WING_SLOT_FILLED;
			} else {
				current.getSlot()->status &= ~WING_SLOT_FILLED;
				current.getSlot()->status |= WING_SLOT_EMPTY;
			}
		} else {
			LuaError(L, "You cannot empty a slot that is ship or weapon locked!");
		}
	}

	return ade_set_args(L, "b", (current.getSlot()->status & WING_SLOT_EMPTY) == 0);
}

ADE_VIRTVAR(isPlayer, l_Loadout_Wing_Slot, nullptr, "If the slot is a player ship", "boolean", "The slot player status")
{
	ss_slot_info_h current;
	if (!ade_get_args(L, "o", l_Loadout_Wing_Slot.Get(&current))) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	bool result = (current.getSlot()->status & WING_SLOT_IS_PLAYER) != 0;
	if (Game_mode & GM_MULTIPLAYER) {
		int index = (current.getWingIndex() * MAX_WING_SLOTS) + current.getSlotIndex();
		result = multi_ts_is_player_in_slot(index);
	} 

	return ade_set_args(L, "b", result);
}

ADE_VIRTVAR(isPlayerAllowed, l_Loadout_Wing_Slot, nullptr, "If the slot is allowed to have player ship. In single player this is functionally the same as isPlayer.", "boolean", "The slot player allowed status")
{
	ss_slot_info_h current;
	if (!ade_get_args(L, "o", l_Loadout_Wing_Slot.Get(&current))) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	bool result = (current.getSlot()->status & WING_SLOT_IS_PLAYER) != 0;
	if (Game_mode & GM_MULTIPLAYER) {
		int index = (current.getWingIndex() * MAX_WING_SLOTS) + current.getSlotIndex();
		result = multi_ts_is_player_allowed_in_slot(index);
	}

	return ade_set_args(L, "b", result);
}

// Probably don't need this one!
ADE_VIRTVAR(ShipClassIndex,
	l_Loadout_Wing_Slot,
	nullptr,
	"The index of the ship class assigned to the slot",
	"number",
	"The ship class index")
{
	ss_slot_info_h current;
	if (!ade_get_args(L, "o", l_Loadout_Wing_Slot.Get(&current))) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	return ade_set_args(L, "i", (current.getSlot()->original_ship_class + 1));
}

ADE_VIRTVAR(Callsign,
	l_Loadout_Wing_Slot,
	nullptr,
	"The callsign of the ship slot. In multiplayer this may be the player's callsign.",
	"string",
	"the callsign")
{
	ss_slot_info_h current;
	if (!ade_get_args(L, "o", l_Loadout_Wing_Slot.Get(&current))) {
		return ADE_RETURN_NIL;
	}
	
	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	char name[NAME_LENGTH];
	ss_return_name(current.getWingIndex(), current.getSlotIndex(), name);

	return ade_set_args(L, "s", name);
}

//**********HANDLE: loadout amount
ADE_OBJ(l_Loadout_Amount, wss_unit_count_h, "loadout_amount", "Loadout handle");

ADE_INDEXER(l_Loadout_Amount,
	"number bank, number amount",
	"Array of ship bank weapons. 1-3 are Primary weapons. 4-7 are Secondary weapons. Note that banks "
	"that do not exist on the ship class are still valid here as a loadout slot. Also note that "
	"primary banks will hold the value of 1 even if it is ballistic. If the amount to set is greater than "
	"the bank's capacity then it will be set to capacity. Set to -1 to empty the slot. Amounts less than -1 will be set to -1.",
	"number",
	"Amount of the currently loaded weapon, -1 if bank has no weapon, or nil if the ship or index is invalid")
{
	wss_unit_count_h current;
	int idx = -1;
	int amount;
	if (!ade_get_args(L, "oi|i", l_Loadout_Amount.Get(&current), &idx, &amount))
		return ADE_RETURN_NIL;

	if (idx < 1 || idx > MAX_SHIP_WEAPONS) {
		return ADE_RETURN_NIL;
	};

	idx--; // Convert from Lua
	if (ADE_SETTING_VAR) {
		if (Game_mode & GM_MULTIPLAYER) {
			LuaError(L, "This property may not be modified in multiplayer.");
			return ADE_RETURN_NIL;
		}
		ship_info* sip = &Ship_info[current.getBank()->ship_class];
		int widx = current.getBank()->wep[idx];
		if (widx >= 0 && widx < (int)Weapon_info.size()) {
			weapon_info* wip = &Weapon_info[widx];
			int capacity = 0;
			// Calculate max capacity of the weapon in the current bank
			if (wip->subtype == WP_LASER) {
				capacity = 1;
			} else {
				capacity = wl_calc_missile_fit(widx, sip->secondary_bank_ammo_capacity[idx - MAX_SHIP_PRIMARY_BANKS]);
			}
			if (amount > capacity) {
				amount = capacity;
			}
			if (amount < -1) {
				amount = -1;
			}
		} else {
			Warning(LOCATION, "Could not set amount for loadout weapon slot %i because the loaded weapon is invalid!", idx);
			amount = -1;
		}
		current.getBank()->wep_count[idx] = amount;
	}

	return ade_set_args(L, "i", current.getBank()->wep_count[idx]);
}

ADE_FUNC(__len, l_Loadout_Amount, nullptr, "The number of weapon banks in the slot", "number", "The number of banks.")
{
	return ade_set_args(L, "i", MAX_SHIP_WEAPONS);
}

//**********HANDLE: loadout weapon
ADE_OBJ(l_Loadout_Weapon, wss_unit_wep_h, "loadout_weapon", "Loadout handle");

ADE_INDEXER(l_Loadout_Weapon,
	"number bank, number WeaponIndex",
	"Array of ship bank weapons. 1-3 are Primary weapons. 4-7 are Secondary weapons. Note that banks "
	"that do not exist on the ship class are still valid here as a loadout slot. When setting the weapon "
	"it will be checked if it is valid for the ship and bank. If it is not then it will be set to -1 and the "
	"amount will be set to -1. If it is valid for the ship then the amount is set to 0. Use .Amounts to set "
	"the amount afterwards. Set to -1 to empty the slot.",
	"number",
	"index into Weapon Classes, 0 if bank is empty, -1 if the ship cannot carry the weapon, or nil if the ship or index is invalid")
{
	wss_unit_wep_h current;
	int bank = -1;
	int wepIndex;
	if (!ade_get_args(L, "oi|i", l_Loadout_Weapon.Get(&current), &bank, &wepIndex))
		return ADE_RETURN_NIL;

	if (bank < 1 || bank > MAX_SHIP_WEAPONS) {
		return ADE_RETURN_NIL;
	};

	ship_info* sip = &Ship_info[current.getBank()->ship_class];
	int bankType = -1;
	// Decide if we're setting a valid primary or secondary bank on the current ship class
	if (bank <= sip->num_primary_banks) {
		bankType = WP_LASER;
	} else if (bank <= (sip->num_secondary_banks + MAX_SHIP_PRIMARY_BANKS)) {
		bankType = WP_MISSILE;
	}

	wepIndex--; // Convert from Lua
	bank--; //Convert from Lua
	if (ADE_SETTING_VAR) {
		if (Game_mode & GM_MULTIPLAYER) {
			LuaError(L, "This property may not be modified in multiplayer.");
			return ADE_RETURN_NIL;
		}
		if (bankType == -1 || wepIndex > weapon_info_size()) {
			LuaError(L, "The provided bank or weapon index is invalid!");
		} else {
			bool valid = false;
			//First we check that this is a valid bank for the ship and that the script is not trying to empty the bank
			if (wepIndex > -1) {
				// Next we check that this is a weapon the ship can carry
				if (eval_weapon_flag_for_game_type(sip->restricted_loadout_flag[bank])) {
					if (eval_weapon_flag_for_game_type(sip->allowed_bank_restricted_weapons[bank][wepIndex])) {
						valid = true;
					}
				} else {
					if (eval_weapon_flag_for_game_type(sip->allowed_weapons[wepIndex])) {
						valid = true;
					}
				}
			}
			if (valid) {
				//Now we double check that we're putting a primary in a primary slot or secondary in a secondary slot
				weapon_info* wip = &Weapon_info[wepIndex];
				if (wip->subtype == bankType) {
					current.getBank()->wep[bank] = wepIndex;
				} else {
					LuaError(L, "Cannot put a primary in a secondary bank or a secondary in a primary bank!");
				}
				current.getBank()->wep_count[bank] = 0;
			}
			else {
				//If the ship cannot carry this weapon in this bank then we set it to -1 and the amount to -1
				current.getBank()->wep[bank] = -1;
				current.getBank()->wep_count[bank] = -1;
			}
		}
	}

	return ade_set_args(L, "i", current.getBank()->wep[bank] + 1);
}

ADE_FUNC(__len, l_Loadout_Weapon, nullptr, "The number of weapon banks in the slot", "number", "The number of banks.")
{
	return ade_set_args(L, "i", MAX_SHIP_WEAPONS);
}

//**********HANDLE: loadout ship
ADE_OBJ_NO_MULTI(l_Loadout_Ship, int, "loadout_ship", "Loadout handle");

ADE_VIRTVAR(ShipClassIndex,
	l_Loadout_Ship,
	"number",
	"The index of the Ship Class. When setting the ship class this will also set the weapons to empty slots. Use "
	".Weapons and .Amounts to set those afterwards. Set to -1 to empty the slot and be sure to set the slot to empty "
	"using Loadout_Wings[slot].isFilled.",
	"number",
	"The index or nil if handle is invalid")
{
	int current;
	int shipIndex;
	if (!ade_get_args(L, "o|i", l_Loadout_Ship.Get(&current), &shipIndex)) {
		return ADE_RETURN_NIL;
	}

	shipIndex--; //Convert from Lua

	if (ADE_SETTING_VAR) {
		if (Game_mode & GM_MULTIPLAYER) {
			LuaError(L, "This property may not be modified in multiplayer.");
			return ADE_RETURN_NIL;
		}
		if (shipIndex > -1) {
			// If we're not trying to empty the slot then make sure it's a valid ship index
			if (shipIndex > ship_info_size()) {
				LuaError(L, "The provided ship index is invalid!");
			} else {
				Wss_slots[current].ship_class = shipIndex;
				//Reset all currently loaded weapons here
				for (int i = 0; i < MAX_SHIP_WEAPONS; i++) {
					Wss_slots[current].wep[i] = -1;
					Wss_slots[current].wep_count[i] = -1;
				}
			}
		} else {
			Wss_slots[current].ship_class = -1;
		}
	}

	return ade_set_args(L, "i", (Wss_slots[current].ship_class + 1));
}

ADE_VIRTVAR(Weapons,
	l_Loadout_Ship,
	nullptr,
	"Array of weapons in the loadout slot",
	"loadout_weapon",
	"The weapons array or nil if handle is invalid")
{
	int current;
	if (!ade_get_args(L, "o", l_Loadout_Ship.Get(&current))) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	return ade_set_args(L, "o", l_Loadout_Weapon.Set(wss_unit_wep_h(current)));
}

ADE_VIRTVAR(Amounts,
	l_Loadout_Ship,
	nullptr,
	"Array of weapon amounts in the loadout slot",
	"loadout_amount",
	"The weapon amounts array or nil if handle is invalid")
{
	int current;
	if (!ade_get_args(L, "o", l_Loadout_Ship.Get(&current))) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	return ade_set_args(L, "o", l_Loadout_Amount.Set(wss_unit_count_h(current)));
}

//**********HANDLE: loadout wing
ADE_OBJ(l_Loadout_Wing, ss_wing_info_h, "loadout_wing", "Loadout handle");

ADE_INDEXER(l_Loadout_Wing,
	"number idx",
	"Array of loadout wing slot data",
	"loadout_wing_slot",
	"loadout slot handle, or invalid handle if index is invalid")
{
	ss_wing_info_h current;
	int idx;
	if (!ade_get_args(L, "oi", l_Loadout_Wing.Get(&current), &idx))
		return ade_set_error(L, "s", "");
	idx--; // Convert to Lua's 1 based index system
	return ade_set_args(L, "o", l_Loadout_Wing_Slot.Set(ss_slot_info_h(current.getWing()->ss_slots, idx, current.getWingIndex())));
}

//This seems superfluous because the loadout wing slots is always max but not only is it something scripters may expect,
//but also if max wings is ever expanded this will automatically reflect that
ADE_FUNC(__len, l_Loadout_Wing, nullptr, "The number of slots in the wing", "number", "The number of slots.")
{
	return ade_set_args(L, "i", MAX_WING_SLOTS);
}

ADE_VIRTVAR(Name, l_Loadout_Wing, nullptr, "The name of the wing", "string", "The wing")
{
	ss_wing_info_h current;
	if (!ade_get_args(L, "o", l_Loadout_Wing.Get(&current))) {
		return ADE_RETURN_NIL;
	}

	if (ADE_SETTING_VAR) {
		LuaError(L, "This property is read only.");
	}

	wing* wp;
	wp = &Wings[current.getWing()->wingnum];

	return ade_set_args(L, "s", wp->name);
}

} // namespace api
} // namespace scripting