1 //
2 //
3 
4 #include "testing.h"
5 
6 #include "scripting/api/objs/vecmath.h"
7 #include "scripting/api/objs/enums.h"
8 #include "scripting/api/objs/texture.h"
9 #include "scripting/api/objs/object.h"
10 #include "scripting/api/objs/particle.h"
11 
12 #include "scripting/lua/LuaValue.h"
13 
14 #include "scripting/api/objs/bytearray.h"
15 #include "scripting/api/objs/audio_stream.h"
16 #include "sound/audiostr.h"
17 
18 #include "physics/physics.h"
19 #include "graphics/2d.h"
20 #include "io/timer.h"
21 #include "particle/particle.h"
22 #include "playerman/player.h"
23 #include "cutscene/movie.h"
24 #include "network/multi_options.h"
25 
26 
27 namespace scripting {
28 namespace api {
29 
30 //*************************Testing stuff*************************
31 //This section is for stuff that's considered experimental.
32 ADE_LIB(l_Testing, "Testing", "ts", "Experimental or testing stuff");
33 
34 ADE_FUNC(openAudioStreamMem,
35 	l_Testing,
36 	"string snddata, enumeration stream_type /* AUDIOSTREAM_* values */",
37 	"Opens an audio stream of the specified in-memory file contents and type.",
38 	"audio_stream",
39 	"A handle to the opened stream or invalid on error")
40 {
41 	luacpp::LuaValue snddata_arr(L);
42 	enum_h streamTypeEnum;
43 	if (!ade_get_args(L, "ao", &snddata_arr, l_Enum.Get(&streamTypeEnum))) {
44 		return ade_set_args(L, "o", l_AudioStream.Set(-1));
45 	}
46 
47 	int streamType;
48 	switch (streamTypeEnum.index) {
49 	case LE_ASF_EVENTMUSIC:
50 		streamType = ASF_EVENTMUSIC;
51 		break;
52 	case LE_ASF_MENUMUSIC:
53 		streamType = ASF_MENUMUSIC;
54 		break;
55 	case LE_ASF_VOICE:
56 		streamType = ASF_VOICE;
57 		break;
58 	default:
59 		LuaError(L, "Invalid audio stream type %d.", streamTypeEnum.index);
60 		return ade_set_args(L, "o", l_AudioStream.Set(-1));
61 	}
62 
63 
64 	if (!snddata_arr.pushValue(L))
65 	    return ade_set_args(L, "o", l_AudioStream.Set(-1));
66     if (!lua_isstring(L, -1)) {
67         lua_pop(L, 1);
68         LuaError(L, "Expected binary string containing audio.");
69         return ade_set_args(L, "o", l_AudioStream.Set(-1));
70     }
71 
72     size_t snd_len;
73     auto snddata = lua_tolstring(L, -1, &snd_len);
74 
75     int ah = audiostream_open_mem(reinterpret_cast<const uint8_t *>(snddata), snd_len, streamType);
76 	lua_pop(L, 1);
77     if (ah < 0) {
78         LuaError(L,"Stream could not be opened. Did you pass valid audio?");
79         return ade_set_args(L, "o", l_AudioStream.Set(-1));
80     }
81 
82 	return ade_set_args(L, "o", l_AudioStream.Set(ah));
83 }
84 
85 
86 ADE_FUNC(avdTest, l_Testing, NULL, "Test the AVD Physics code", NULL, NULL)
87 {
88 	(void)L; // unused parameter
89 
90 	static bool initialized = false;
91 	static avd_movement avd;
92 
93 	if(!initialized)
94 	{
95 		avd.setAVD(10.0f, 3.0f, 1.0f, 1.0f, 0.0f);
96 		initialized = true;
97 	}
98 	for(int i = 0; i < 3000; i++)
99 	{
100 		float Pc, Vc;
101 		avd.get((float)i/1000.0f, &Pc, &Vc);
102 		gr_set_color(0, 255, 0);
103 		gr_pixel(i/10, gr_screen.clip_bottom - (int)(Pc*10.0f), GR_RESIZE_NONE);
104 		gr_set_color(255, 0, 0);
105 		gr_pixel(i/10, gr_screen.clip_bottom - (int)(Vc*10.0f), GR_RESIZE_NONE);
106 
107 		avd.get(&Pc, &Vc);
108 		gr_set_color(255, 255, 255);
109 		gr_pixel((timestamp()%3000)/10, gr_screen.clip_bottom - (int)(Pc*10.0f), GR_RESIZE_NONE);
110 		gr_pixel((timestamp()%3000)/10, gr_screen.clip_bottom - (int)(Vc*10.0f), GR_RESIZE_NONE);
111 	}
112 
113 	return ADE_RETURN_NIL;
114 }
115 
116 ADE_FUNC_DEPRECATED(createParticle,
117 	l_Testing,
118 	"vector Position, vector Velocity, number Lifetime, number Radius, enumeration Type, [number "
119 	"TracerLength=-1, boolean Reverse=false, texture Texture=Nil, object AttachedObject=Nil]",
120 	"Creates a particle. Use PARTICLE_* enumerations for type."
121 	"Reverse reverse animation, if one is specified"
122 	"Attached object specifies object that Position will be (and always be) relative to.",
123 	"particle",
124 	"Handle to the created particle",
125 	gameversion::version(19, 0, 0, 0),
126 	"Not available in the testing library anymore. Use gr.createPersistentParticle instead.")
127 {
128 	particle::particle_info pi;
129 	pi.type = particle::PARTICLE_DEBUG;
130 	pi.optional_data = -1;
131 	pi.attached_objnum = -1;
132 	pi.attached_sig = -1;
133 	pi.reverse = 0;
134 
135 	// Need to consume tracer_length parameter but it isn't used anymore
136 	float temp;
137 
138 	enum_h *type = NULL;
139 	bool rev=false;
140 	object_h *objh=NULL;
141 	texture_h* texture = nullptr;
142 	if (!ade_get_args(L, "ooffo|fboo", l_Vector.Get(&pi.pos), l_Vector.Get(&pi.vel), &pi.lifetime, &pi.rad,
143 	                  l_Enum.GetPtr(&type), &temp, &rev, l_Texture.GetPtr(&texture), l_Object.GetPtr(&objh)))
144 		return ADE_RETURN_NIL;
145 
146 	if(type != NULL)
147 	{
148 		switch(type->index)
149 		{
150 			case LE_PARTICLE_DEBUG:
151 				pi.type = particle::PARTICLE_DEBUG;
152 				break;
153 			case LE_PARTICLE_FIRE:
154 				pi.type = particle::PARTICLE_FIRE;
155 				break;
156 			case LE_PARTICLE_SMOKE:
157 				pi.type = particle::PARTICLE_SMOKE;
158 				break;
159 			case LE_PARTICLE_SMOKE2:
160 				pi.type = particle::PARTICLE_SMOKE2;
161 				break;
162 			case LE_PARTICLE_BITMAP:
163 			    if (texture == nullptr || !texture->isValid()) {
164 				    LuaError(L, "Invalid texture specified for createParticle()!");
165 				    return ADE_RETURN_NIL;
166 			    } else {
167 				    pi.optional_data = texture->handle;
168 				    pi.type          = particle::PARTICLE_BITMAP;
169 			    }
170 			    break;
171 		}
172 	}
173 
174 	if(rev)
175 		pi.reverse = 0;
176 
177 	if(objh != NULL && objh->IsValid())
178 	{
179 		pi.attached_objnum = OBJ_INDEX(objh->objp);
180 		pi.attached_sig = objh->objp->signature;
181 	}
182 
183 	particle::WeakParticlePtr p = particle::createPersistent(&pi);
184 
185 	if (!p.expired())
186 		return ade_set_args(L, "o", l_Particle.Set(particle_h(p)));
187 	else
188 		return ADE_RETURN_NIL;
189 }
190 
191 ADE_FUNC(getStack, l_Testing, NULL, "Generates an ADE stackdump", "string", "Current Lua stack")
192 {
193 	char buf[10240] = {'\0'};
194 	ade_stackdump(L, buf);
195 	return ade_set_args(L, "s", buf);
196 }
197 
198 ADE_FUNC(isCurrentPlayerMulti, l_Testing, NULL, "Returns whether current player is a multiplayer pilot or not.", "boolean", "Whether current player is a multiplayer pilot or not")
199 {
200 	if(Player == NULL)
201 		return ade_set_error(L, "b", false);
202 
203 	if(!(Player->flags & PLAYER_FLAGS_IS_MULTI))
204 		return ADE_RETURN_FALSE;
205 
206 	return ADE_RETURN_TRUE;
207 }
208 
209 ADE_FUNC(isPXOEnabled, l_Testing, NULL, "Returns whether PXO is currently enabled in the configuration.", "boolean", "Whether PXO is enabled or not")
210 {
211 	if(!(Multi_options_g.pxo))
212 		return ADE_RETURN_FALSE;
213 
214 	return ADE_RETURN_TRUE;
215 }
216 
217 ADE_FUNC(playCutscene, l_Testing, NULL, "Forces a cutscene by the specified filename string to play. Should really only be used in a non-gameplay state (i.e. start of GS_STATE_BRIEFING) otherwise odd side effects may occur. Highly Experimental.", "string", NULL)
218 {
219 	//This whole thing is a quick hack and can probably be done way better, but is currently functioning fine for my purposes.
220 	const char* filename;
221 
222 	if (!ade_get_args(L, "s", &filename))
223 		return ADE_RETURN_FALSE;
224 
225 	movie::play(filename);
226 
227 	return ADE_RETURN_TRUE;
228 }
229 
230 
231 }
232 }
233 
234