diff --git a/code/parse/lua.cpp b/code/parse/lua.cpp index 8bd6aa5ccf..6c4891c171 100644 --- a/code/parse/lua.cpp +++ b/code/parse/lua.cpp @@ -20,6 +20,7 @@ #include "weapon/weapon.h" #include "parse/parselo.h" #include "render/3d.h" +#include "particle/particle.h" //*************************Lua funcs************************* int script_remove_lib(lua_State *L, char *name); @@ -1799,53 +1800,6 @@ LUA_FUNC(getBreed, l_Object, NULL, "Object type name", "Gets object type") return lua_set_args(L, "s", Object_type_names[objh->objp->type]); } -LUA_FUNC(fetchShieldStrength, l_Object, "[Shield Quadrant], [New value]", "[New] shield strength", - "Returns total shield strength if no quadrant is specified, or individual quadrant strength if one is specified." - "Valid quadrants are \"Front\", \"Back\", \"Left\", and \"Right\". Specifying a new value will set the specified quadrant to that amount. " - "\"None\" may be used for the new value to be divided equally between all quadrants") -{ - object_h *objh; - char *qd = NULL; - float nval = -1.0f; - if(!lua_get_args(L, "o|sf", l_Object.GetPtr(&objh), &qd, &nval)) - return 0; - - if(!objh->IsValid()) - return LUA_RETURN_NIL; - - object *objp = objh->objp; - - //Which quadrant? - int qdx=-1; - if(qd == NULL || !stricmp(qd, "None")) - qdx = -1; - else if(!stricmp(qd, "Top")) - qdx = 0; - else if(!stricmp(qd, "Left")) - qdx = 1; - else if(!stricmp(qd, "Right")) - qdx = 2; - else if(!stricmp(qd, "Bottom")) - qdx = 3; - else - return LUA_RETURN_NIL; - - //Set/get all quadrants - if(qdx == -1) { - if(nval >= 0.0f) - set_shield_strength(objp, nval); - - return lua_set_args(L, "f", get_shield_strength(objp)); - } - - //Set one quadrant? - if(nval >= 0.0f) - objp->shield_quadrant[qdx] = nval; - - //Get one quadrant - return lua_set_args(L, "f", objp->shield_quadrant[qdx]); -} - //**********CLASS: Mounted Weapons struct ship_weapon_h : public object_h { @@ -2130,199 +2084,7 @@ LUA_VAR(AWACSRadius, l_Subsystem, "Number", "Subsystem AWACS radius") return lua_set_args(L, "f", sso->ss->awacs_radius); } - -//**********CLASS: Ship -lua_obj l_Ship("ship", "Ship object", &l_Object); - -LUA_FUNC(fetchName, l_Ship, "[New name]", "[New] ship name (string)", "Gets ship name") -{ - object_h *objh; - char *s = NULL; - if(!lua_get_args(L, "o|f", l_Ship.GetPtr(&objh), &s)) - return LUA_RETURN_NIL; - - if(!objh->IsValid()) - return LUA_RETURN_NIL; - - ship *shipp = &Ships[objh->objp->instance]; - - if(s == NULL) { - strncpy(shipp->ship_name, s, sizeof(shipp->ship_name)-1); - } - - return lua_set_args(L, "s", shipp->ship_name); -} - -LUA_FUNC(getClass, l_Ship, NULL, "Ship class handle (shipclass)", "Gets ship class handle") -{ - object_h *objh; - if(!lua_get_args(L, "o|f", l_Ship.GetPtr(&objh))) - return LUA_RETURN_NIL; - - if(!objh->IsValid()) - return LUA_RETURN_NIL; - - return lua_set_args(L, "o", l_Shipclass.Set(Ships[objh->objp->instance].ship_info_index)); -} - -LUA_FUNC(getMountedWeapons, l_Ship, "[Subsystem name]", "mountedweapons object, or false if invalid subsystem specified", "Gets weapons mounted on a ship or subsystem") -{ - object_h *objh; - char *s=NULL; - if(!lua_get_args(L, "o|s", l_Ship.GetPtr(&objh), &s)) - return 0; - - if(!objh->IsValid()) - return LUA_RETURN_NIL; - - ship_weapon_h mw(objh->objp, NULL); - - if(s == NULL) - { - mw.sw = NULL; - return lua_set_args(L, "o", l_MountedWeapons.Set(mw)); - } - - ship_subsys *ss = ship_get_subsys(&Ships[objh->objp->instance], s); - if(ss == NULL) - return LUA_RETURN_FALSE; - - mw.sw = &ss->weapons; - - return lua_set_args(L, "o", l_MountedWeapons.Set(mw)); -} - -LUA_FUNC(fetchAfterburnerFuel, l_Ship, "[Fuel amount]", "[New] fuel amount", "Returns ship fuel amount, or sets it if amount is specified") -{ - object_h *objh; - float fuel = -1.0f; - if(!lua_get_args(L, "o|f", l_Ship.GetPtr(&objh), &fuel)) - return LUA_RETURN_NIL; - - if(!objh->IsValid()) - return LUA_RETURN_NIL; - - ship *shipp = &Ships[objh->objp->instance]; - - if(fuel >= 0.0f) - shipp->afterburner_fuel = fuel; - - return lua_set_args(L, "f", shipp->afterburner_fuel); -} - -LUA_FUNC(warpIn, l_Ship, NULL, "True", "Warps ship in") -{ - object_h *objh; - if(!lua_get_args(L, "o", l_Ship.GetPtr(&objh))) - return LUA_RETURN_NIL; - - if(!objh->IsValid()) - return LUA_RETURN_NIL; - - shipfx_warpin_start(objh->objp); - - return LUA_RETURN_TRUE; -} - -LUA_FUNC(warpOut, l_Ship, NULL, "True", "Warps ship out") -{ - object_h *objh; - if(!lua_get_args(L, "o", l_Ship.GetPtr(&objh))) - return LUA_RETURN_NIL; - - if(!objh->IsValid()) - return LUA_RETURN_NIL; - - shipfx_warpout_start(objh->objp); - - return LUA_RETURN_TRUE; -} - -//**********HANDLE: Wing -lua_obj l_Wing("wing", "Wing handle"); - -LUA_INDEXER(l_Wing, "Index", "Ship", "Ship via number in wing") -{ - int wdx; - int sdx; - object_h *ndx=NULL; - if(!lua_get_args(L, "oi|o", l_Wing.Get(&wdx), &sdx, l_Ship.GetPtr(&ndx))) - return LUA_RETURN_NIL; - - if(sdx < Wings[wdx].current_count) { - return LUA_RETURN_NIL; - } - - if(LUA_SETTING_VAR && ndx != NULL && ndx->IsValid()) { - Wings[wdx].ship_index[sdx] = ndx->objp->instance; - } - - return lua_set_args(L, "o", l_Ship.Set(object_h(&Objects[Ships[Wings[wdx].ship_index[sdx]].objnum]))); -} -//**********OBJECT: Player -lua_obj l_Player("player", "Player object"); - -int player_helper(lua_State *L, int *idx) -{ - if(!lua_get_args(L, "o", l_Player.Get(idx))) - return 0; - - if(*idx < 0 || *idx > Player_num) - return 0; - - return 1; -} - -LUA_FUNC(getName, l_Player, NULL, "Player name (string)", "Gets current player name") -{ - int idx; - player_helper(L, &idx); - - return lua_set_args(L, "s", Players[idx].callsign); -} - -LUA_FUNC(getImage, l_Player, NULL, "Player image (string)", "Gets current player image") -{ - int idx; - player_helper(L, &idx); - - return lua_set_args(L, "s", Players[idx].image_filename); -} - -LUA_FUNC(getSquadronName, l_Player, NULL, "Squad name (string)", "Gets current player squad name") -{ - int idx; - player_helper(L, &idx); - - return lua_set_args(L, "s", Players[idx].squad_name); -} -//WMC - This isn't working -/* -LUA_FUNC(getSquadronImage, l_Player, NULL, "Squad image (string)", "Gets current player squad image") -{ - int idx; - player_helper(L, &idx); - - return lua_set_args(L, "s", Players[idx].squad_filename); -}*/ - -LUA_FUNC(getCampaignName, l_Player, NULL, "Campaign name (string)", "Gets current player campaign") -{ - int idx; - player_helper(L, &idx); - - return lua_set_args(L, "s", Players[idx].current_campaign); -} - -LUA_FUNC(getMainHall, l_Player, NULL, "Main hall number", "Gets player's main hall number") -{ - int idx; - player_helper(L, &idx); - - return lua_set_args(L, "i", (int)Players[idx].main_hall); -} - -//**********LIBRARY: Texture +//**********HANDLE: Texture lua_obj l_Texture("texture", "Texture handle"); //WMC - int should NEVER EVER be an invalid handle. Return Nil instead. Nil FTW. @@ -2428,6 +2190,291 @@ LUA_FUNC(getFPS, l_Texture, NULL, "Texture FPS", "Gets frames-per-second of text return lua_set_args(L, "i", fps); } + +//**********HANDLE: Textures +struct ship_textures_h : public object_h +{ + ship_textures_h(object *objp) : object_h(objp){} +}; + +lua_obj l_ShipTextures("shiptextures", "Ship textures"); + +LUA_INDEXER(l_ShipTextures, "Texture name or index", "Texture", "Ship textures") +{ + ship_textures_h *sh; + char *s; + int tdx=-1; + if(!lua_get_args(L, "os|o", l_ShipTextures.GetPtr(&sh), &s, l_Texture.Get(&tdx))) + return LUA_RETURN_NIL; + + if(!sh->IsValid() || s==NULL) + return LUA_RETURN_NIL; + + ship *shipp = &Ships[sh->objp->instance]; + polymodel *pm = model_get(shipp->modelnum); + int idx = -1; + int i; + + char fname[MAX_FILENAME_LEN]; + char *p; + for(i = 0; i < pm->n_textures; i++) + { + if(pm->textures[i] > -1) + { + bm_get_filename(pm->textures[i], fname); + + //Get rid of extension + p = strchr( fname, '.' ); + if ( p != NULL) + *p = 0; + + if(!stricmp(fname, s)) { + idx = i; + break; + } + } + + if(shipp->replacement_textures != NULL && pm->textures[i] > -1) + { + bm_get_filename(shipp->replacement_textures[i], fname); + //Get rid of extension + p = strchr( fname, '.' ); + if ( p != NULL) + *p = 0; + + if(!stricmp(fname, s)) { + idx = i; + break; + } + } + } + + if(idx < 0) + { + i = atoi(s); + i--; //Lua->FS2 + if(i < 0 || i >= pm->n_textures || (pm->textures[i] < 0 && shipp->replacement_textures[i] < 0)) + return LUA_RETURN_FALSE; + } + + if(LUA_SETTING_VAR && tdx > -1) { + shipp->replacement_textures = shipp->replacement_textures_buf; + shipp->replacement_textures[idx] = tdx; + } + + if(shipp->replacement_textures != NULL && shipp->replacement_textures[idx] > -1) + return lua_set_args(L, "o", l_Texture.Set(shipp->replacement_textures[idx])); + else + return lua_set_args(L, "o", l_Texture.Set(pm->textures[idx])); +} + +//**********CLASS: Ship +lua_obj l_Ship("ship", "Ship object", &l_Object); + +LUA_VAR(Name, l_Ship, "String", "Ship name") +{ + object_h *objh; + char *s = NULL; + if(!lua_get_args(L, "o|f", l_Ship.GetPtr(&objh), &s)) + return LUA_RETURN_NIL; + + if(!objh->IsValid()) + return LUA_RETURN_NIL; + + ship *shipp = &Ships[objh->objp->instance]; + + if(LUA_SETTING_VAR && s != NULL) { + strncpy(shipp->ship_name, s, sizeof(shipp->ship_name)-1); + } + + return lua_set_args(L, "s", shipp->ship_name); +} + +LUA_VAR(Textures, l_Ship, "shiptextures", "Gets ship textures") +{ + object_h *objh; + ship_textures_h *th; + if(!lua_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_ShipTextures.GetPtr(&th))) + return LUA_RETURN_NIL; + + if(!objh->IsValid()) + return LUA_RETURN_NIL; + + if(LUA_SETTING_VAR && th != NULL && th->IsValid()) { + ship *src = &Ships[objh->objp->instance]; + ship *dest = &Ships[th->objp->instance]; + if(src->replacement_textures != NULL) + { + dest->replacement_textures = dest->replacement_textures_buf; + memcpy(dest->replacement_textures_buf, src->replacement_textures_buf, sizeof(dest->replacement_textures_buf)); + } + } + + return lua_set_args(L, "o", l_ShipTextures.Set(ship_textures_h(objh->objp))); +} + +LUA_VAR(AfterburnerFuel, l_Ship, "Number", "Afterburner fuel amount") +{ + object_h *objh; + float fuel = -1.0f; + if(!lua_get_args(L, "o|f", l_Ship.GetPtr(&objh), &fuel)) + return LUA_RETURN_NIL; + + if(!objh->IsValid()) + return LUA_RETURN_NIL; + + ship *shipp = &Ships[objh->objp->instance]; + + if(LUA_SETTING_VAR && fuel >= 0.0f) + shipp->afterburner_fuel = fuel; + + return lua_set_args(L, "f", shipp->afterburner_fuel); +} + +LUA_VAR(MountedWeapons, l_Ship, "mountedweapons", "Weapons mounted on ship") +{ + object_h *objh; + ship_weapon_h *swh; + if(!lua_get_args(L, "o|o", l_Ship.GetPtr(&objh), l_MountedWeapons.GetPtr(&swh))) + return LUA_RETURN_NIL; + + if(!objh->IsValid()) + return LUA_RETURN_NIL; + + ship_weapon_h mw(objh->objp, NULL); + + if(LUA_SETTING_VAR && swh != NULL && swh->IsValid()) + { + Ships[objh->objp->instance].weapons = Ships[swh->objp->instance].weapons; + } + + return lua_set_args(L, "o", l_MountedWeapons.Set(mw)); +} + +LUA_FUNC(getClass, l_Ship, NULL, "Ship class handle (shipclass)", "Gets ship class handle") +{ + object_h *objh; + if(!lua_get_args(L, "o|f", l_Ship.GetPtr(&objh))) + return LUA_RETURN_NIL; + + if(!objh->IsValid()) + return LUA_RETURN_NIL; + + return lua_set_args(L, "o", l_Shipclass.Set(Ships[objh->objp->instance].ship_info_index)); +} + +LUA_FUNC(warpIn, l_Ship, NULL, "True", "Warps ship in") +{ + object_h *objh; + if(!lua_get_args(L, "o", l_Ship.GetPtr(&objh))) + return LUA_RETURN_NIL; + + if(!objh->IsValid()) + return LUA_RETURN_NIL; + + shipfx_warpin_start(objh->objp); + + return LUA_RETURN_TRUE; +} + +LUA_FUNC(warpOut, l_Ship, NULL, "True", "Warps ship out") +{ + object_h *objh; + if(!lua_get_args(L, "o", l_Ship.GetPtr(&objh))) + return LUA_RETURN_NIL; + + if(!objh->IsValid()) + return LUA_RETURN_NIL; + + shipfx_warpout_start(objh->objp); + + return LUA_RETURN_TRUE; +} + +//**********HANDLE: Wing +lua_obj l_Wing("wing", "Wing handle"); + +LUA_INDEXER(l_Wing, "Index", "Ship", "Ship via number in wing") +{ + int wdx; + int sdx; + object_h *ndx=NULL; + if(!lua_get_args(L, "oi|o", l_Wing.Get(&wdx), &sdx, l_Ship.GetPtr(&ndx))) + return LUA_RETURN_NIL; + + if(sdx < Wings[wdx].current_count) { + return LUA_RETURN_NIL; + } + + if(LUA_SETTING_VAR && ndx != NULL && ndx->IsValid()) { + Wings[wdx].ship_index[sdx] = ndx->objp->instance; + } + + return lua_set_args(L, "o", l_Ship.Set(object_h(&Objects[Ships[Wings[wdx].ship_index[sdx]].objnum]))); +} +//**********HANDLE: Player +lua_obj l_Player("player", "Player object"); + +int player_helper(lua_State *L, int *idx) +{ + if(!lua_get_args(L, "o", l_Player.Get(idx))) + return 0; + + if(*idx < 0 || *idx > Player_num) + return 0; + + return 1; +} + +LUA_FUNC(getName, l_Player, NULL, "Player name (string)", "Gets current player name") +{ + int idx; + player_helper(L, &idx); + + return lua_set_args(L, "s", Players[idx].callsign); +} + +LUA_FUNC(getImage, l_Player, NULL, "Player image (string)", "Gets current player image") +{ + int idx; + player_helper(L, &idx); + + return lua_set_args(L, "s", Players[idx].image_filename); +} + +LUA_FUNC(getSquadronName, l_Player, NULL, "Squad name (string)", "Gets current player squad name") +{ + int idx; + player_helper(L, &idx); + + return lua_set_args(L, "s", Players[idx].squad_name); +} +//WMC - This isn't working +/* +LUA_FUNC(getSquadronImage, l_Player, NULL, "Squad image (string)", "Gets current player squad image") +{ + int idx; + player_helper(L, &idx); + + return lua_set_args(L, "s", Players[idx].squad_filename); +}*/ + +LUA_FUNC(getCampaignName, l_Player, NULL, "Campaign name (string)", "Gets current player campaign") +{ + int idx; + player_helper(L, &idx); + + return lua_set_args(L, "s", Players[idx].current_campaign); +} + +LUA_FUNC(getMainHall, l_Player, NULL, "Main hall number", "Gets player's main hall number") +{ + int idx; + player_helper(L, &idx); + + return lua_set_args(L, "i", (int)Players[idx].main_hall); +} + //**********LIBRARY: Base lua_lib l_Base("Base", "ba", "Base Freespace 2 functions"); @@ -3031,6 +3078,85 @@ LUA_FUNC(getScreenHeight, l_Graphics, NULL, "Height in pixels (Number)", "Gets s return lua_set_args(L, "i", gr_screen.max_h); } +LUA_FUNC(setTarget, l_Graphics, "[texture Texture]", "True if successful, false otherwise", + "If texture is specified, sets current rendering surface to a texture." + "Otherwise, sets rendering surface back to screen.") +{ + int idx = -1; + lua_get_args(L, "|o", l_Texture.Get(&idx)); + + bool b = bm_set_render_target(idx); + + return lua_set_args(L, "b", b); +} + +LUA_FUNC(setColor, l_Graphics, "Red, Green, Blue, [alpha]", NULL, "Sets 2D drawing color") +{ + if(!Gr_inited) + return LUA_RETURN_NIL; + + int r,g,b,a=255; + + if(!lua_get_args(L, "iii|i", &r, &g, &b, &a)) + return LUA_RETURN_NIL; + + color ac; + gr_init_alphacolor(&ac,r,g,b,a); + gr_set_color_fast(&ac); + + return 0; +} + +LUA_FUNC(setOpacity, l_Graphics, "Opacity %, [Opacity Type]", NULL, + "Sets opacity for 2D image drawing functions to specified amount and type. Valid types are:" + "
None" + "
Filter") +{ + float f; + char *s=NULL; + int idx=-1; + + if(!lua_get_args(L, "f|s", &f, &s)) + return LUA_RETURN_NIL; + + if(f > 100.0f) + f = 100.0f; + if(f < 0.0f) + f = 0.0f; + + if(s != NULL) + { + if(!stricmp(s, "Filter")) + idx = GR_ALPHABLEND_FILTER; + else + idx = GR_ALPHABLEND_NONE; + } + + lua_Opacity = f*0.01f; + if(idx > -1) + lua_Opacity_type = idx; + + return LUA_RETURN_NIL; +} + +LUA_FUNC(setFont, l_Graphics, "Font index", NULL, "Sets current font") +{ + if(!Gr_inited) + return LUA_RETURN_NIL; + + int fn; + + if(!lua_get_args(L, "i", &fn)) + return LUA_RETURN_NIL; + + //Lua->FS2 + fn--; + + gr_set_font(fn); + + return 0; +} + #define MAX_TEXT_LINES 256 LUA_FUNC(drawString, l_Graphics, "String, x1, y1, [Resize], [x2], [y2]", NULL, "Draws a string") @@ -3113,73 +3239,6 @@ LUA_FUNC(getTextHeight, l_Graphics, NULL, "Text height", "Gets current font's he return lua_set_args(L, "i", gr_get_font_height()); } -LUA_FUNC(setColor, l_Graphics, "Red, Green, Blue, [alpha]", NULL, "Sets 2D drawing color") -{ - if(!Gr_inited) - return LUA_RETURN_NIL; - - int r,g,b,a=255; - - if(!lua_get_args(L, "iii|i", &r, &g, &b, &a)) - return LUA_RETURN_NIL; - - color ac; - gr_init_alphacolor(&ac,r,g,b,a); - gr_set_color_fast(&ac); - - return 0; -} - -LUA_FUNC(setOpacity, l_Graphics, "Opacity %, [Opacity Type]", NULL, - "Sets opacity for 2D image drawing functions to specified amount and type. Valid types are:" - "
None" - "
Filter") -{ - float f; - char *s=NULL; - int idx=-1; - - if(!lua_get_args(L, "f|s", &f, &s)) - return LUA_RETURN_NIL; - - if(f > 100.0f) - f = 100.0f; - if(f < 0.0f) - f = 0.0f; - - if(s != NULL) - { - if(!stricmp(s, "Filter")) - idx = GR_ALPHABLEND_FILTER; - else - idx = GR_ALPHABLEND_NONE; - } - - lua_Opacity = f*0.01f; - if(idx > -1) - lua_Opacity_type = idx; - - return LUA_RETURN_NIL; -} - -LUA_FUNC(setFont, l_Graphics, "Font index", NULL, "Sets current font") -{ - if(!Gr_inited) - return LUA_RETURN_NIL; - - int fn; - - if(!lua_get_args(L, "i", &fn)) - return LUA_RETURN_NIL; - - //Lua->FS2 - fn--; - - gr_set_font(fn); - - return 0; -} - LUA_FUNC(drawPixel, l_Graphics, "x, y, [Resize]", NULL, "Sets pixel to current color") { if(!Gr_inited) @@ -3328,6 +3387,27 @@ LUA_FUNC(drawMonochromeImage, l_Graphics, "Image name, x, y, [Resize], [Width to return lua_set_args(L, "b", true); } +LUA_FUNC(createTexture, l_Graphics, "Width, Height, Type", "Handle to new texture", "Creates a texture for rendering to. Types are static - for infrequent rendering - and dynamic - for frequent rendering.") +{ + int w,h; + char *s; + if(!lua_get_args(L, "iis", &w, &h, &s)) + return LUA_RETURN_NIL; + + int t = 0; + if(!stricmp(s, "Static")) + t = BMP_TEX_STATIC_RENDER_TARGET; + else if(!stricmp(s, "Dynamic")) + t = BMP_TEX_DYNAMIC_RENDER_TARGET; + + int idx = bm_make_render_target(w, h, t); + + if(idx < 0) + return LUA_RETURN_NIL; + + return lua_set_args(L, "o", l_Texture.Set(idx)); +} + LUA_FUNC(loadTexture, l_Graphics, "Texture filename, [Load if Animation], [No drop frames]", "Texture handle, false if invalid name", "Gets a handle to a texture. If second argument is set to true, animations will also be loaded." "If third argument is set to true, every other animation frame will not be loaded if system has less than 48 MB memory." @@ -3515,7 +3595,54 @@ LUA_FUNC(playInterfaceSound, l_SoundLib, "Sound filename", "True if sound was pl //This section is for stuff that's considered experimental. lua_lib l_Testing("Testing", "ts", "Experimental or testing stuff"); +LUA_FUNC(createParticle, l_Testing, "vector Position, vector Velocity, number Lifetime, number Radius, string Type, [number Tracer length=-1, boolean Reverse=false, texture Texture=Nil, object Attached Object=Nil]", NULL, + "Creates a particle. Types are 'Debug', 'Bitmap', 'Fire', 'Smoke', 'Smoke2', and 'Persistent Bitmap'." + "Reverse reverse animation, if one is specified" + "Attached object specifies object that Position will be (and always be) relative to.") +{ + particle_info pi; + pi.type = PARTICLE_DEBUG; + pi.optional_data = 0; + pi.tracer_length = 1.0f; + pi.attached_objnum = -1; + pi.attached_sig = -1; + pi.reverse = 0; + char *s=NULL; + bool rev=false; + object_h *objh=NULL; + if(!lua_get_args(L, "ooffs|fboo", l_Vector.Get(&pi.pos), l_Vector.Get(&pi.vel), &pi.lifetime, &pi.rad, &s, &pi.tracer_length, &rev, l_Texture.Get((int*)&pi.optional_data), l_Object.GetPtr(&objh))) + return LUA_RETURN_NIL; + + if(s != NULL) + { + if(!stricmp(s, "Debug")) + pi.type = PARTICLE_DEBUG; + else if(!stricmp(s, "Bitmap")) + pi.type = PARTICLE_BITMAP; + else if(!stricmp(s, "Fire")) + pi.type = PARTICLE_FIRE; + else if(!stricmp(s, "Smoke")) + pi.type = PARTICLE_SMOKE; + else if(!stricmp(s, "Smoke2")) + pi.type = PARTICLE_SMOKE2; + else if(!stricmp(s, "Persistent bitmap")) + pi.type = PARTICLE_BITMAP_PERSISTENT; + } + + if(rev) + pi.reverse = 0; + + if(objh != NULL && objh->IsValid()) + { + pi.attached_objnum = OBJ_INDEX(objh->objp); + pi.attached_sig = objh->objp->signature; + } + + particle_create(&pi); + + return LUA_RETURN_NIL; +} // *************************Housekeeping************************* diff --git a/code/parse/lua.h b/code/parse/lua.h index 26fe1d33da..2dfce19125 100644 --- a/code/parse/lua.h +++ b/code/parse/lua.h @@ -250,7 +250,7 @@ struct object_h { int sig; bool IsValid(){return objp->signature == sig;} - object_h(object *objp){objp=objp; sig=objp->signature;} + object_h(object *in){objp=in; sig=in->signature;} }; //*************************Lua globals************************* diff --git a/code/parse/scripting.cpp b/code/parse/scripting.cpp index 2127b21382..751f6ef1dc 100644 --- a/code/parse/scripting.cpp +++ b/code/parse/scripting.cpp @@ -164,7 +164,7 @@ void script_state::RemGlobal(char *name) int script_state::LoadBm(char *name) { - for(int i = 0; i < ScriptImages.size(); i++) + for(int i = 0; i < (int)ScriptImages.size(); i++) { if(!stricmp(name, ScriptImages[i].fname)) return ScriptImages[i].handle; @@ -184,7 +184,7 @@ int script_state::LoadBm(char *name) void script_state::UnloadImages() { - for(int i = 0; i < ScriptImages.size(); i++) + for(int i = 0; i < (int)ScriptImages.size(); i++) { bm_unload(ScriptImages[i].handle); } @@ -377,6 +377,67 @@ int script_state::OutputMeta(char *filename) return 1; } +bool script_state::EvalString(char* string, char *format, void *rtn, char *debug_str) +{ + char *lcp = &string[strlen(string)-1]; + char lastchar = *lcp; + + if(string[0] == '{') + { +#ifdef USE_PYTHON + if(lastchar == '}') + { + *lcp = '\0'; + } + else + { + return false; + } + + //WMC - Whoever comes next to Python...needs to fix this. + Py_RunString(string, Py_file_input, PyGlb, PyLoc); + + *lcp = lastchar; + return true; +#else + return false; +#endif + } + char *s = string; + if(string[0] != '[') + { + s = new char[strlen(string) + 8]; + strcpy(s, "return "); + strcpy(s, string); + } + else if(lastchar != ']') + { + return false; + } + else + { + *lcp = '\0'; + } + + //WMC - Push error handling function + lua_pushcfunction(LuaState, lua_friendly_error); + //Parse string + luaL_loadbuffer(LuaState, s, strlen(s), "SEXP"); + //Call function + if(!lua_pcall(LuaState, 0, 1, -2)) + { + return false; + } + + //Default return if no return - 0 + lua_get_args(LuaState, format, *(script_lua_odata*)rtn); + + if(lastchar == ']') + *lcp = lastchar; + + return true; +} + script_hook script_state::ParseChunk(char* debug_str) { static int total_parse_calls = 0; @@ -423,12 +484,12 @@ script_hook script_state::ParseChunk(char* debug_str) //luaL_loadfile(GetLuaSession(), filename); rval.index = luaL_ref(GetLuaSession(), LUA_REGISTRYINDEX); + vm_free(raw_lua); } #endif //dealloc //WMC - For some reason these cause crashes //vm_free(filename); - //vm_free(raw_lua); } else if(check_for_string("[")) { @@ -447,7 +508,6 @@ script_hook script_state::ParseChunk(char* debug_str) rval.index = luaL_ref(GetLuaSession(), LUA_REGISTRYINDEX); #endif //free the mem - //WTF THIS CRASHES //vm_free(raw_lua); } else if(check_for_string("{")) @@ -463,22 +523,23 @@ script_hook script_state::ParseChunk(char* debug_str) //Add it to the lib rval.index = PyBytecodeLib.Add(PyBytecode(Py_CompileString(raw_python, debug_str, Py_file_input))); #endif - //WTF THIS CRASHES - //vm_free(raw_python); + vm_free(raw_python); } else { - //Python eval - //Maybe remove this and force brackets, or use custom system? + //Assume lua + rval.language = SC_LUA; - //Assume python - rval.language = SC_PYTHON; + strcpy(buf, "return "); //Stuff it - stuff_string(buf, F_RAW, NULL, sizeof(buf)-1); -#ifdef USE_PYTHON - //Add it to the lib - rval.index = PyBytecodeLib.Add(PyBytecode(Py_CompileString(buf, debug_str, Py_eval_input)); + stuff_string(buf+strlen(buf), F_RAW, NULL, sizeof(buf)-1); +#ifdef USE_LUA + //Load it into a buffer & parse it + luaL_loadbuffer(GetLuaSession(), buf, strlen(buf), debug_str); + + //Stick it in the registry + rval.index = luaL_ref(GetLuaSession(), LUA_REGISTRYINDEX); #endif } diff --git a/code/parse/scripting.h b/code/parse/scripting.h index 2021e0c67a..fa873d4667 100644 --- a/code/parse/scripting.h +++ b/code/parse/scripting.h @@ -73,6 +73,7 @@ public: void RemGlobal(char *name); //Hook handling functions + bool EvalString(char* string, char *format, void *rtn, char *debug_str); script_hook ParseChunk(char* debug_str=NULL); int RunBytecode(script_hook &hd, char format='\0', void *data=NULL); }; diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index 50b0feb01e..0ea72eff8c 100644 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -9,13 +9,17 @@ /* * $Logfile: /Freespace2/code/parse/SEXP.CPP $ - * $Revision: 2.204 $ - * $Date: 2006-01-20 04:33:21 $ - * $Author: Goober5000 $ + * $Revision: 2.205 $ + * $Date: 2006-01-21 09:36:58 $ + * $Author: wmcoolmon $ * * main sexpression generator * * $Log: not supported by cvs2svn $ + * Revision 2.204 2006/01/20 04:33:21 Goober5000 + * fixed a sexp help message + * --Goober5000 + * * Revision 2.203 2006/01/19 03:17:12 phreak * give repair-subsystem and set-subsystem-strength a fourth optional parameter used to possibly regenerate the submodel of a given subsystem * sabotage-subsystem should make the subsystems explode @@ -1186,6 +1190,8 @@ #include "network/multimsgs.h" #include "network/multiutil.h" #include "network/multi_team.h" +#include "parse/lua.h" +#include "parse/scripting.h" #ifndef NDEBUG #include "hud/hudmessage.h" @@ -1581,6 +1587,9 @@ sexp_oper Operators[] = { { "show-jumpnode", OP_JUMP_NODE_SHOW_JUMPNODE, 1, 1, }, { "hide-jumpnode", OP_JUMP_NODE_HIDE_JUMPNODE, 1, 1, }, + { "script-eval-num", OP_SCRIPT_EVAL_NUM, 1, 1, }, + { "script-eval-string", OP_SCRIPT_EVAL_STRING, 1, 1, }, + { "do-nothing", OP_NOP, 0, 0, }, }; @@ -13636,6 +13645,18 @@ void sexp_hide_jumpnode(int n) jnp->show(false); } +//WMC - This is a bit of a hack, however, it's easier than +//coding in a whole new SCript_system function. +int sexp_script_eval(int n, bool return_text) +{ + char *s = CTEXT(n); + + int r = -1; + Script_system.EvalString(s, "|i", &r, "SEXP"); + + return r; +} + // high-level sexpression evaluator int eval_sexp(int cur_node, int referenced_node) { @@ -15043,6 +15064,14 @@ int eval_sexp(int cur_node, int referenced_node) sexp_hide_jumpnode(node); break; + case OP_SCRIPT_EVAL_NUM: + sexp_val = sexp_script_eval(node, false); + break; + + case OP_SCRIPT_EVAL_STRING: + sexp_val = sexp_script_eval(node, true); + break; + default: Error(LOCATION, "Looking for SEXP operator, found '%s'.\n", CTEXT(cur_node)); break; @@ -15292,6 +15321,8 @@ int query_operator_return_type(int op) case OP_GET_OBJECT_RELATIVE_X: case OP_GET_OBJECT_RELATIVE_Y: case OP_GET_OBJECT_RELATIVE_Z: + case OP_SCRIPT_EVAL_NUM: + case OP_SCRIPT_EVAL_STRING: return OPR_NUMBER; case OP_ABS: @@ -16733,6 +16764,10 @@ int query_operator_argument_type(int op, int argnum) if (argnum == 1) return OPF_BOOL; else return OPF_NEBULA_POOF; + case OP_SCRIPT_EVAL_NUM: + case OP_SCRIPT_EVAL_STRING: + return OPF_STRING; + default: Int3(); } @@ -20003,6 +20038,18 @@ sexp_help_struct Sexp_help[] = { "\t2:\tA True boolean expression will toggle this poof on. A false one will do the opposite." }, + {OP_SCRIPT_EVAL_NUM, "script-eval-num\r\n" + "\tEvaluates script to return a number" + "Takes 1 argument...\r\n" + "\t1:\tScript\r\n" + }, + + {OP_SCRIPT_EVAL_STRING, "script-eval-string\r\n" + "\tEvaluates script to return a string" + "Takes 1 argument...\r\n" + "\t1:\tScript\r\n" + }, + }; diff --git a/code/parse/sexp.h b/code/parse/sexp.h index 266a024c53..7cc1c4e8b2 100644 --- a/code/parse/sexp.h +++ b/code/parse/sexp.h @@ -9,13 +9,16 @@ /* * $Source: /cvs/cvsroot/fs2open/fs2_open/code/parse/sexp.h,v $ - * $Revision: 2.101 $ + * $Revision: 2.102 $ * $Author: wmcoolmon $ - * $Date: 2006-01-06 04:18:55 $ + * $Date: 2006-01-21 09:36:58 $ * * header for sexpression parsing * * $Log: not supported by cvs2svn $ + * Revision 2.101 2006/01/06 04:18:55 wmcoolmon + * turret-target-order SEXPs, ship thrusters + * * Revision 2.100 2005/12/31 01:47:35 wmcoolmon * num-within-box * @@ -994,6 +997,8 @@ struct ship_subsys; #define OP_CURRENT_SPEED (0x002b | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) // WMCoolmon #define OP_IS_IFF (0x002c | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) #define OP_NUM_WITHIN_BOX (0x002d | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) // WMCoolmon +#define OP_SCRIPT_EVAL_NUM (0x002e | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) // WMCoolmon +#define OP_SCRIPT_EVAL_STRING (0x002f | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) // WMCoolmon // conditional sexpressions #define OP_WHEN (0x0000 | OP_CATEGORY_CONDITIONAL) diff --git a/code/particle/particle.cpp b/code/particle/particle.cpp index 7dfe9fa12c..cb8b1c295c 100644 --- a/code/particle/particle.cpp +++ b/code/particle/particle.cpp @@ -9,13 +9,17 @@ /* * $Logfile: /Freespace2/code/Particle/Particle.cpp $ - * $Revision: 2.16 $ - * $Date: 2005-09-24 02:43:33 $ - * $Author: Goober5000 $ + * $Revision: 2.17 $ + * $Date: 2006-01-21 09:36:58 $ + * $Author: wmcoolmon $ * * Code for particle system * * $Log: not supported by cvs2svn $ + * Revision 2.16 2005/09/24 02:43:33 Goober5000 + * whoops + * --Goober5000 + * * Revision 2.14 2005/06/19 09:00:09 taylor * minor sanity checking for geometry_batcher * make particle batchers allocate dynamically @@ -488,7 +492,7 @@ KillAnother: } } -void particle_create( vec3d *pos, vec3d *vel, float lifetime, float rad, int type, uint optional_data ) +void particle_create( vec3d *pos, vec3d *vel, float lifetime, float rad, int type, uint optional_data, float tracer_length, object *objp, bool reverse ) { particle_info pinfo; @@ -502,9 +506,17 @@ void particle_create( vec3d *pos, vec3d *vel, float lifetime, float rad, int typ // setup new data pinfo.tracer_length = -1.0f; - pinfo.attached_objnum = -1; - pinfo.attached_sig = -1; - pinfo.reverse = 0; + if(objp == NULL) + { + pinfo.attached_objnum = -1; + pinfo.attached_sig = -1; + } + else + { + pinfo.attached_objnum = OBJ_INDEX(objp); + pinfo.attached_sig = objp->signature; + } + pinfo.reverse = reverse? 1 : 0; // lower level function particle_create(&pinfo); diff --git a/code/particle/particle.h b/code/particle/particle.h index 1ae3f50d3c..33fae7067f 100644 --- a/code/particle/particle.h +++ b/code/particle/particle.h @@ -9,13 +9,17 @@ /* * $Logfile: /Freespace2/code/Particle/Particle.h $ - * $Revision: 2.6 $ - * $Date: 2005-07-13 03:35:34 $ - * $Author: Goober5000 $ + * $Revision: 2.7 $ + * $Date: 2006-01-21 09:36:58 $ + * $Author: wmcoolmon $ * * Includes for particle system * * $Log: not supported by cvs2svn $ + * Revision 2.6 2005/07/13 03:35:34 Goober5000 + * remove PreProcDefine #includes in FS2 + * --Goober5000 + * * Revision 2.5 2005/06/19 09:00:09 taylor * minor sanity checking for geometry_batcher * make particle batchers allocate dynamically @@ -156,7 +160,7 @@ typedef struct particle_info { // Creates a single particle. See the PARTICLE_?? defines for types. void particle_create( particle_info *pinfo ); -void particle_create( vec3d *pos, vec3d *vel, float lifetime, float rad, int type, uint optional_data = 0 ); +void particle_create( vec3d *pos, vec3d *vel, float lifetime, float rad, int type, uint optional_data=0, float tracer_length=-1.0f, struct object *objp=NULL, bool reverse=false ); //============================================================================ diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 368531807f..51ae34df16 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -10,13 +10,16 @@ /* * $Logfile: /Freespace2/code/Ship/Ship.cpp $ - * $Revision: 2.299 $ - * $Date: 2006-01-17 03:45:32 $ - * $Author: phreak $ + * $Revision: 2.300 $ + * $Date: 2006-01-21 09:36:58 $ + * $Author: wmcoolmon $ * * Ship (and other object) handling functions * * $Log: not supported by cvs2svn $ + * Revision 2.299 2006/01/17 03:45:32 phreak + * Rearranged the rearming code so it doesn't potentially take 2 minutes to reload a single bomb. + * * Revision 2.298 2006/01/16 11:02:23 wmcoolmon * Various warning fixes, scripting globals fix; added "plr" and "slf" global variables for in-game hooks; various lua functions; GCC fixes for scripting. * @@ -5698,7 +5701,7 @@ void ship_render(object * obj) // small ships if((The_mission.flags & MISSION_FLAG_FULLNEB) && (si->flags & SIF_SMALL_SHIP)){ // force detail levels - float fog_val = neb2_get_fog_intensity(obj); + float fog_val = neb2_get_fog_intensity(obj); if(fog_val >= 0.6f){ model_set_detail_level(2); model_render( shipp->modelnum, &obj->orient, &obj->pos, render_flags | MR_LOCK_DETAIL, OBJ_INDEX(obj), -1, shipp->replacement_textures );