1 //
2 //
3 
4 #include "debris.h"
5 #include "object.h"
6 #include "shipclass.h"
7 #include "debris/debris.h"
8 #include "globalincs/linklist.h"
9 #include "ship/ship.h"
10 
11 namespace scripting {
12 namespace api {
13 
14 
15 //**********HANDLE: Debris
16 ADE_OBJ_DERIV(l_Debris, object_h, "debris", "Debris handle", l_Object);
17 
18 ADE_VIRTVAR(IsHull, l_Debris, "boolean", "Whether or not debris is a piece of hull", "boolean", "Whether debris is a hull fragment, or false if handle is invalid")
19 {
20 	object_h *oh;
21 	bool b=false;
22 	if(!ade_get_args(L, "o|b", l_Debris.GetPtr(&oh), &b))
23 		return ade_set_error(L, "b", false);
24 
25 	if(!oh->IsValid())
26 		return ade_set_error(L, "b", false);
27 
28 	debris *db = &Debris[oh->objp->instance];
29 
30 	if(ADE_SETTING_VAR) {
31 		db->is_hull = b ? 1 : 0;
32 	}
33 
34 	return ade_set_args(L, "b", db->is_hull ? true : false);
35 
36 }
37 
38 ADE_VIRTVAR(OriginClass, l_Debris, "shipclass", "The shipclass of the ship this debris originates from", "shipclass", "The shipclass of the ship that created this debris")
39 {
40 	object_h *oh;
41 	int shipIdx = -1;
42 	if(!ade_get_args(L, "o|o", l_Debris.GetPtr(&oh), &shipIdx))
43 		return ade_set_error(L, "o", l_Shipclass.Set(-1));
44 
45 	if(!oh->IsValid())
46 		return ade_set_error(L, "o", l_Shipclass.Set(-1));
47 
48 	debris *db = &Debris[oh->objp->instance];
49 
50 	if(ADE_SETTING_VAR) {
51 		if (shipIdx >= 0 && shipIdx < ship_info_size())
52 			db->ship_info_index = shipIdx;
53 	}
54 
55 	return ade_set_args(L, "o", l_Shipclass.Set(db->ship_info_index));
56 }
57 
58 ADE_VIRTVAR(DoNotExpire, l_Debris, "boolean", "Whether the debris should expire.  Normally, debris does not expire if it is from ships destroyed before mission or from ships that are more than 50 meters in radius.", "boolean", "True if flag is set, false if flag is not set and nil on error")
59 {
60 	object_h *objh = nullptr;
61 	bool set = false;
62 
63 	if (!ade_get_args(L, "o|b", l_Debris.GetPtr(&objh), &set))
64 		return ADE_RETURN_NIL;
65 
66 	if (!objh->IsValid())
67 		return ADE_RETURN_NIL;
68 
69 	debris *db = &Debris[objh->objp->instance];
70 
71 	if (ADE_SETTING_VAR)
72 	{
73 		db->flags.set(Debris_Flags::DoNotExpire, set);
74 
75 		// we need to be careful to manage the hull list here
76 		// per comments in debris.cpp: "pieces that ... have the DoNotExpire flag should not be on it"
77 		if (db->is_hull)
78 		{
79 			if (set)
80 				debris_remove_from_hull_list(db);
81 			else
82 				debris_add_to_hull_list(db);
83 		}
84 	}
85 
86 	if (db->flags[Debris_Flags::DoNotExpire])
87 		return ADE_RETURN_TRUE;
88 	else
89 		return ADE_RETURN_FALSE;
90 }
91 
92 ADE_VIRTVAR(LifeLeft, l_Debris, "number", "The time this debris piece will last.  When this is 0 (and DoNotExpire is false) the debris will explode.", "number", "The amount of time, in seconds, the debris will last")
93 {
94 	object_h *objh = nullptr;
95 	float lifeleft = 0.0f;
96 
97 	if (!ade_get_args(L, "o|f", l_Debris.GetPtr(&objh), &lifeleft))
98 		return ADE_RETURN_NIL;
99 
100 	if (!objh->IsValid())
101 		return ADE_RETURN_NIL;
102 
103 	debris *db = &Debris[objh->objp->instance];
104 
105 	if (ADE_SETTING_VAR)
106 		db->lifeleft = lifeleft;
107 
108 	return ade_set_args(L, "f", lifeleft);
109 }
110 
111 ADE_FUNC(getDebrisRadius, l_Debris, NULL, "The radius of this debris piece", "number", "The radius of this debris piece or -1 if invalid")
112 {
113 	object_h *oh;
114 	if(!ade_get_args(L, "o", l_Debris.GetPtr(&oh)))
115 		return ade_set_error(L, "f", -1.0f);
116 
117 	if(!oh->IsValid())
118 		return ade_set_error(L, "f", -1.0f);
119 
120 	debris *db = &Debris[oh->objp->instance];
121 
122 	polymodel *pm = model_get(db->model_num);
123 
124 	if (pm == NULL)
125 		return ade_set_error(L, "f", -1.0f);
126 
127 	if (db->submodel_num < 0 || pm->n_models <= db->submodel_num)
128 		return ade_set_error(L, "f", -1.0f);
129 
130 	return ade_set_error(L, "f", pm->submodel[db->submodel_num].rad);
131 }
132 
133 ADE_FUNC(isValid, l_Debris, NULL, "Return if this debris handle is valid", "boolean", "true if valid false otherwise")
134 {
135 	object_h *oh;
136 	if(!ade_get_args(L, "o", l_Debris.GetPtr(&oh)))
137 		return ADE_RETURN_FALSE;
138 
139 	return ade_set_args(L, "b", oh != NULL && oh->IsValid());
140 }
141 
142 ADE_FUNC(isGeneric, l_Debris, nullptr, "Return if this debris is the generic debris model, not a model subobject", "boolean", "true if Debris_model")
143 {
144 	object_h *oh;
145 	if (!ade_get_args(L, "o", l_Debris.GetPtr(&oh)))
146 		return ADE_RETURN_FALSE;
147 
148 	if (!oh->IsValid())
149 		return ADE_RETURN_FALSE;
150 
151 	debris *db = &Debris[oh->objp->instance];
152 
153 	return ade_set_args(L, "b", debris_is_generic(db));
154 }
155 
156 ADE_FUNC(isVaporized, l_Debris, nullptr, "Return if this debris is the vaporized debris model, not a model subobject", "boolean", "true if Debris_vaporize_model")
157 {
158 	object_h *oh;
159 	if (!ade_get_args(L, "o", l_Debris.GetPtr(&oh)))
160 		return ADE_RETURN_FALSE;
161 
162 	if (!oh->IsValid())
163 		return ADE_RETURN_FALSE;
164 
165 	debris *db = &Debris[oh->objp->instance];
166 
167 	return ade_set_args(L, "b", debris_is_vaporized(db));
168 }
169 
170 ADE_FUNC(vanish, l_Debris, nullptr, "Vanishes this piece of debris from the mission.", "boolean", "True if the deletion was successful, false otherwise.")
171 {
172 
173 	object_h* oh = nullptr;
174 	if (!ade_get_args(L, "o", l_Debris.GetPtr(&oh)))
175 		return ade_set_error(L, "b", false);
176 
177 	if (!oh->IsValid())
178 		return ade_set_error(L, "b", false);
179 
180 	//This skips all the fancy deathroll stuff, and just cleans it from the mission
181 	oh->objp->flags.set(Object::Object_Flags::Should_be_dead);
182 
183 	return ade_set_args(L, "b", true);
184 }
185 
186 }
187 }
188