Hard Light Productions Forums
Modding, Mission Design, and Coding => FS2 Open Coding - The Source Code Project (SCP) => Topic started by: Nuke on September 14, 2006, 03:08:34 pm
-
i was thinking it might be very usefull to have metadata fields in various game files that can be accessed by the scripting system. variables can be read, written, created, or deleted from theese metafields. good places to have metafields would be the player files (theyre being redone anyway, right), missions and campaign files, tables, perhps models as well (META chunk, or stored in submodel properties). most of the metafields would be in read only mode, so as not to screw with multiplayer. player files would be the only exception, as this is the best place to store dynamic variables, for things like cashflow and legal status. the read only fields are to allow modders to add data that will be handled by script and ignored by the engine. this also allows modders with no scripting ability to use scripts other people have written. for example if i were to write a script for atmospheric flight physics, modders can add metatags to tables for lift characteristics and drag, and missions get the option wether or not to use activate that part of the script. it seems like it could be very a very versitile feature that could be implemented with very little hassle. all the text based formats can be edited to include meta very easily, player meta fields would be added dynamically through scripting. the scripting system would need to be modified to recieve and edit metafields, and the engine would need exceptions to allow the fields to be presant and not cause an error. it would really add versatility to the whole thing.
-
Paragraphs?
-
Lua does have builtin file I/O functions. They're not a very good choice for Linux compatibility (Unless you go to the trouble of checking for and saving in the user's home directory), but it wouldn't be impossible to add the default Freespace 2 write functions.
-
Could we use the forthcoming ship or rather shipclass specific scripts (with scripting tbms) for dealing atleast part of this stuff?
-
Could we use the forthcoming ship or rather shipclass specific scripts (with scripting tbms) for dealing atleast part of this stuff?
along those lines mission and campaign specific scripts (possibly imbedded).
Paragraphs?
dude, it was barely long enough to require any line breaks :hopping:
-
Dude, paragraphs are A-1 SUPAR.
-
Dude, paragraphs are A-1 SUPAR.
But it's much easier to ignore them when you actually have to work to make sense of their posts. When I see something like that, I just ignore it, since it's one less feature to have to spend time on. :D
-
But it's much easier to ignore them when you actually have to work to make sense of their posts. When I see something like that, I just ignore it, since it's one less feature to have to spend time on. :D
You know, I end up doing the same thing, but this is the first time I've seen it spelled out in words. Brilliant. :) That can be one of our stock rejection criteria: didn't bother to format his post; doesn't respect the coders; request denied; thread closed. :D
-
Oh, come on; that is a paragraph. It doesn't even come out to half a screen at 1024x768. :p
-
Well, to be fair to both sides, Nuke has some great ideas and is one of the few people really using the engine's features to their utmost, but then I can understand why the last thing a coder wants to see is a request that doesn't even include Captitalisation and comes in one big lump of text. So I'd say 6 of one, half dozen of the other ;)
-
well I hope this thread can be salvaged.
-
wow, a complement, thanks flip :D
well the idea is to make scripts more portable. lets say im a modeler (well i am:D) but i havent a clue how to write script. lua is gibbrish to me, but this other guy he does know how to write script. so the moddeler wants to make a sidefire bomber. we can point the gunpoints to the side, but we cant lock onto the target because its not in the hud its on the side. no problem wel use dumbfire bombs, but how to aim them? a sidefire gunsight. but i dont know how to write lua! oh no, so much for my cool idea. but this other guy wrote a script for a non line-of-sight targeting. unfortunately it requires i enter the gunpoint position and normal, but i cant read lua!
this is where metafields become handy. instead of editing the script, the modeler can just punch in a custom table tag which is only read by script, and ignored by the engine. this lets modders pass variables to script without editing script. it lets scripters write scripts with parts that can be turned on or off depending on the extra variables in the various entries in the tables, mission files, or campaign files. for example to only enable a fog radar script only when a custom boolean variable is set to true. the main point is to make it so scripts dont have to be re-written or edited every time new content is added.
the playerfile meta fields are to allow for more customizable gameplay. theyre the only fields that should be able to change from script. its mainly for things like a trade engine or an open universe. you can store money or cargo manifests, system location. for my mod i want to have an arms dealer and a loot system where pirated goods can be traded for weapons and ammo. its important however to note the player file metadata serves a different purpose. it has nothing to do with script portability and everything to do wint changing gameplay.
its really 2 ideas. but they would greatly increase the possibilities of the scripting system.
-
Could we use the forthcoming ship or rather shipclass specific scripts (with scripting tbms) for dealing atleast part of this stuff?
along those lines mission and campaign specific scripts (possibly imbedded).
I'm not quite sure what he ship/shipclass-specific scripts would have to do with Nuke's original idea?
And mission and campaign-specific scripts should easily be possible either through the new conditional hooks, or by simple use of conditionals :p
-
I should also take this opportunity to point out a shift I've been thinking about...
With variables now working, I think I may understand why my ill-fated attempts at an library-defined arrays didn't pay off. So I was thinking of replacing the currently-cumbersome functions of:
--Get the last created ship in the mission
numships = mn.getNumShips()
loser = mn.getShipByIndex(numships)
--Get Alfalfa 1
ourhero = mn.getShipByName("Alpha 1")
with
numships = #mn.Ships
loser = mn.Ships[numships]
ourhero = mn.Ships["Alpha 1"]
It's much cleaner, but it would break existing scripts if I removed the old functions. Of course I can leave the old functions in, but I'm still trying to avoid locking out syntax improvements for the sake of backwards compatibility, since scripting hasn't yet been included in a major release. (The "#" is a new operator that gets the size of something)
It would apply for pretty much all sets of items referenced with "getNum*" functions.
-
i think scripting is too new to worry about breaking reverse compatability. i really havent written anything major, and it wouldnt be too hard to fix my code. i can see later on, when people start heavily scripting mods, that it could be a problem. were still wrestling with the beast to see what we can make it do.
-
I'm not quite sure what he ship/shipclass-specific scripts would have to do with Nuke's original idea?
And mission and campaign-specific scripts should easily be possible either through the new conditional hooks, or by simple use of conditionals :p
Some referred to the physics thing in which shipclass specific scripts could perhaps act as poor man's table file extensions...
I should also take this opportunity to point out a shift I've been thinking about...
With variables now working, I think I may understand why my ill-fated attempts at an library-defined arrays didn't pay off. So I was thinking of replacing the currently-cumbersome functions of:
--Get the last created ship in the mission
numships = mn.getNumShips()
loser = mn.getShipByIndex(numships)
--Get Alfalfa 1
ourhero = mn.getShipByName("Alpha 1")
with
numships = #mn.Ships
loser = mn.Ships[numships]
ourhero = mn.Ships["Alpha 1"]
It's much cleaner, but it would break existing scripts if I removed the old functions. Of course I can leave the old functions in, but I'm still trying to avoid locking out syntax improvements for the sake of backwards compatibility, since scripting hasn't yet been included in a major release. (The "#" is a new operator that gets the size of something)
It would apply for pretty much all sets of items referenced with "getNum*" functions.
Whichever way is fine for me... i kinda like the current, perhaps tad cumbersome way of doing things though.
i think scripting is too new to worry about breaking reverse compatability. i really havent written anything major, and it wouldnt be too hard to fix my code. i can see later on, when people start heavily scripting mods, that it could be a problem. were still wrestling with the beast to see what we can make it do.
QTF, i'm pretty sure that no one of the current 'scripters' has so much material that this change would be in any way catastrophic to them.
-
i have 4 scripts so far. ones hudpong, anothers a pirate hud, but all i got working so far is the gunsight. i still have the problem of how to aquire aspect lock with targeting overridden. perhaps i can just use heat seekers and find a way to lock the bank uness certain conditions for a lock are met. the other 2 scripts are experimental things, a mouse operated turret, and various particle effects.
-
Are there any other scripting concerns at all that should be addressed?
-
lets see
any chance we can get per-gauge overrides for the hud? i have a new lead indicator i want to use without shutting down the whole hud system.
new object types:
pixel/color object (rgba).
2d vector object
thats all i can think of right now
-
hudpong
is this what i think it is?
imagine... we can start up an extremely processor-intensive, full screen PONG GAME!
-
hudpong
is this what i think it is?
imagine... we can start up an extremely processor-intensive, full screen PONG GAME!
i guess you werent around when i posted the hud pong topic. hud pong essentially lets you play pong on the hud. theres an example script in the wiki under scripting.tbl :D
-
2d vector?
-
essentially x,y coord. i think it would be less cluttersome to have when handeling 2d hud guages. though i suppose i could use the 3d vector object and waste the z coord. :D
however the pixel object is a must cause its rediculous to store each and every pixel i want to store in 4 seprate variables.
another idea i just came up with, it may already be possible thougt. procedural breifing animations that can run in the briefing screen. you could also attain a level of interactivity as well, such as giving the player the option of specifiying capship deployment by drag and drop for example. it souldnt be a replacement of the existing briefing system, but an extension, it should be able to draw on top of the existing fred briefint, and you should also be able to get information such as wether its a command briefing or mission briefing, and what stage of the briefing youre at. also it would be cool if i could say pause the brifing in script, so that the player may be given time to interact with the script, such as deciding where cruiser should jump in at, and then unpause when the user hits the done button. just a thought.
-
Well, you can always override any state you please, and add buttons to already existing screens by defining the hook, not setting the override, and scripting the button as you would normally. Dealing with the briefing screen code is probably a subproject all its own. I remember it being incomprehensible and nasty from when I was working on nonstandard res compatibility.
I agree on the color thing. I need to take a look at the internal color struct and see if I can use it, or if it can be slimmed down. You can, btw, store multiple variables in a table: tutorial (http://lua-users.org/wiki/TablesTutorial). But you're right, it should be a default type.
I'm still a bit skeptical of 2D vectors. It'd be common for 2D stuff, yeah, but I feel like it might be a type that's got so marginal a use that it might be better to just leave it out to avoid needless overhead. (Most of the time, if you're defining a hud gauge, it seems like you'd have a table with the name, coordinates, and whatever other data you want; having a special type for the coordinates would only condense those variables to 1 instead of 2). Plus when displaying lines, you'd want to be incrementing only one variable, while leaving the other alone.
Can you give me an example for 2D vectors?
-
well the reason i want to use vector math is so i can do vector operations (dot product, matrix rotation, ect) on them rather than handle the coords indicidually. my lead indicator is a good example. the guage, when not locked onto something will animate to the screen center, and when locking will move twards the screen coords generated by the leadreticle function. currently its using seprate coords. heres the code in its entirety, so you can see how many variables im using with xy coords.
#Global Hooks
$GameInit:
[
--all this stuff is for multires support, for getting true width and height, and for generating factors to scale coords by
w = gr.getScreenWidth()
h = gr.getScreenHeight()
if w >= 1024 then
wf = w / 1024
else
wf = w / 640
end
if h >= 768 then
hf = h / 768
else
hf = h / 480
end
--now that were done with that ****, we can define some more important vars
cx = w / 2 --screen center constant x
cy = h / 2 --screen center constant y
chx = cx --initial crosshair position x
chy = cy --initial crosshair position y
xtarg = 0 --this is where our crosshair will want to be
ytarg = 0 --same thing but a bit more vertical
xship = 0 --ship coords when on screen
yship = 0 --yep ditto
xdir = 0 --another pair of vars
ydir = 0 --i really need to learn to use arrays
wepvel = 800 --set for thrasher for testing, wel do what wanderer did later
locked = false --this indicates weapon is locked, locked mode means the crosshair is controled directly by the lead code
locking = false --locking means the indicator is in transition between screen center and the target
chr = 50
chg = 50
chb = 50
cha = 50
--now a crosshair, il make this much more detailed later, with target direction and orientation, target iff and maybe ammo gauge and locked/locking indicators
drawgunsight = function(x,y,r,g,b,a)
gr.setColor(r,g,b,a)
gr.drawCircle(100,x,y)
gr.setColor(r,g,b,a+100)
gr.drawGradientLine(x+35,y+35,x+20,y+20)
gr.drawGradientLine(x-35,y+35,x-20,y+20)
gr.drawGradientLine(x+35,y-35,x+20,y-20)
gr.drawGradientLine(x-35,y-35,x-20,y-20)
end
--now for some basic vector maths, theyre probibly in the libs but they werent mentioned in scripting.html
makepos = function(invertme) --simply makes numbers positive if theyre negative
if invertme < 0 then
invertme = invertme * -1
end
return invertme
end
getveclen = function(x1, y1, x2, y2) --calculate the length of a 2d vector
local xdist = x1 - x2
local ydist = y1 - y2
xdist = makepos(xdist)
ydist = makepos(ydist)
local length = math.sqrt((xdist * xdist) + (ydist * ydist)) --Pythagorean theorem mother****er!!!
return length
end
getvecdir = function(x1, y1, x2, y2) --return a normal of length 1, i think
local vlength = getveclen(x1, y1, x2, y2)
local xdist = x2 - x1
local ydist = y2 - y1
if xdist ~= 0 then --dont create a div by 0 error
xdist = xdist / vlength
end
if ydist ~= 0 then
ydist = ydist / vlength
end
return xdist, ydist
end
--and finally lets jack wanderers code, because i really dont feel like plotting vectors in 3d space, maybe wel change some stuff
leadreticle = function(weaponvel) --no need to check if targets nil, i did that already before calling this
local targetpos = target.Position --tweak theese
local targetvel = target.Velocity --looks like nothing else needs to be tweaked here
local lenghttargetvel = targetvel:getMagnitude()
local playerpos = plr.Position
local plrtotrg = playerpos - targetpos
local lenghtplrtotrg = plrtotrg:getMagnitude()
local trgangle = plrtotrg:getDotProduct(targetvel)
local a = (( weaponvel * weaponvel ) - ( lenghttargetvel * lenghttargetvel ))
local b = ( 2 * trgangle )
local c = -( lenghtplrtotrg * lenghtplrtotrg )
local discrim = ((b * b) - 4 * a * c)
if discrim >= 0 and a ~= 0 then
multipl1 = (( -b + math.sqrt(discrim)) / ( 2 * a))
multipl2 = (( -b - math.sqrt(discrim)) / ( 2 * a))
if multipl1 >=0 and multipl1 <= multipl2 and multipl2 >= 0 then
targetmult = multipl1
elseif multipl1 >=0 and multipl2 < 0 then
targetmult = multipl1
elseif multipl2 >=0 then
targetmult = multipl2
else
targetmult = nil
end
if targetmult ~= nil then
local leadvel = targetvel/(1/targetmult)
local leadpos = targetpos + leadvel
if leadpos:getScreenCoords() ~= false then
leadx, leady = leadpos:getScreenCoords() --rather than just simply draw the coords, il scale and return them so my code can **** with them
leadx = leadx * wf --drawleadreticle(leadx,leady) pft, my way is better :D
leady = leady * hf --theese factors make things so much easyer
return leadx, leady --yep, thats what i need there
else
return 0, 0 --return double zero if this all fails, so it doesnt tweak my math
end
end
end
end
]
$HUD:
[
--this stuff finds a target for the leadamajigger
range = wepvel --reset theese each frame before scanning the ship list
target = nil
for i=1, mn.getNumShips() do --find closest target on screen
thing = mn.getShipByIndex(i)
if thing.Position:getScreenCoords() ~= false then
dist = plr.Position:getDistance(thing.Position)
if dist < range then
range = dist
target = thing
end
end
end
--get coords from a target if there was one
if target ~= nil then --if it exists, get the target's screen coords
xtarg, ytarg = leadreticle(wepvel)
if xtarg == 0 and ytarg == 0 then
locked = false
locking = false
else
locking = true
end
if target.Position:getScreenCoords() ~= false then
xship, yship = target.Position:getScreenCoords()
xship = xship * wf
yship = yship * hf
locking = true
else
xship = 0
yship = 0
locked = false
locking = false
end
if locked or locking then
xtarg = cx + (xship - xtarg)
ytarg = cy + (yship - ytarg)
else
xtarg = cx
ytarg = cy
end
else --otherwise target the screen's center
xtarg = cx
ytarg = cy
locked = false
locking = false
end
--make damn sure the crosshair stays on the screen
if chx < 50 * wf then
chx = 50 * wf
locked = false
locking = false
elseif chx > w - (50 * wf) then
chx = w - (50 * wf)
locked = false
locking = false
end
if chy < 50 * hf then
chy = 50 * hf
locked = false
locking = false
elseif chy > h - (50 * hf) then
chy = h - (50 * hf)
locked = false
locking = false
end
--now that weve figured out weather were locked, and onto what if we are, lets move the reticle accordingly
if locked then
chx = xtarg
chy = ytarg
elseif locking then
if getveclen(xtarg, ytarg, chx, chy) > 1 then
xdir, ydir = getvecdir(chx, chy, xtarg, ytarg)
chx = chx + xdir * ba.getFrametime(false) * 180 * wf
chy = chy + ydir * ba.getFrametime(false) * 180 * hf
else
locked = true
locking = false
end
else --we can transition to center now
if getveclen(cx, cy, chx, chy) > 1 then
xdir, ydir = getvecdir(chx, chy, cx, cy)
chx = chx + xdir * ba.getFrametime(false) * 120 * wf
chy = chy + ydir * ba.getFrametime(false) * 120 * hf
else
chx = cx
chy = cy
end
end
--check target iff and animate the colors, god damn thats alot of code
if target == nil then
if chr > 50 then
chr = chr - 1
elseif chr < 50 then
chr = chr + 1
end
if chg > 50 then
chg = chg - 1
elseif chg < 50 then
chg = chg + 1
end
if chb > 50 then
chb = chb - 1
elseif chb < 50 then
chb = chb + 1
end
elseif target.Team.Name == "Hostile" or target.Team.Name == "Traitor" then
if chr < 255 then
chr = chr + 1
end
if chg > 0 then
chg = chg - 1
end
if chb > 0 then
chb = chb - 1
end
elseif target.Team.Name == "Friendly" then
if chr > 0 then
chr = chr - 1
end
if chg < 255 then
chg = chg + 1
end
if chb > 0 then
chb = chb - 1
end
elseif target.Team.Name == "Unknown" then
if chr < 255 then
chr = chr + 1
end
if chg > 0 then
chg = chg - 1
end
if chb < 255 then
chb = chb + 1
end
elseif target.Team.Name == "Neutral" then
if chr > 0 then
chr = chr - 1
end
if chg > 0 then
chg = chg - 1
end
if chb < 255 then
chb = chb + 1
end
else
if chr > 128 then
chr = chr - 1
elseif chr < 128 then
chr = chr + 1
end
if chg > 128 then
chg = chg - 1
elseif chg < 128 then
chg = chg + 1
end
if chb > 128 then
chb = chb - 1
elseif chb < 128 then
chb = chb + 1
end
end
--my nifty fade effect
vl = getveclen(chx, chy, xtarg, ytarg)
vl = math.floor(vl)
if vl < 140 and vl > 20 then
cha = vl
end
--finally draw that sucker
drawgunsight(chx, chy, chr, chg, chb, cha)
]
+Override: true
#End
damn what a mess, this is why im a graphics person. :D it will take me a while to remember how my code worked. ok this code is imortant:
if locked then
chx = xtarg
chy = ytarg
elseif locking then
if getveclen(xtarg, ytarg, chx, chy) > 1 then
xdir, ydir = getvecdir(chx, chy, xtarg, ytarg)
chx = chx + xdir * ba.getFrametime(false) * 180 * wf
chy = chy + ydir * ba.getFrametime(false) * 180 * hf
else
locked = true
locking = false
end
else --we can transition to center now
if getveclen(cx, cy, chx, chy) > 1 then
xdir, ydir = getvecdir(chx, chy, cx, cy)
chx = chx + xdir * ba.getFrametime(false) * 120 * wf
chy = chy + ydir * ba.getFrametime(false) * 120 * hf
else
chx = cx
chy = cy
end
end
ok theese pretty much control how my guage animates between modes. if locked is true then the gauge just renders on the coords returned by the lead reticle function thus no animation code is being used however if locking is true, it means the sight must seek the target coords. this is where 2d fectors coume into play. note i wrote 2 functions for td vector math, getvecdir takes a vector and normalizes it (at least i hope it does, my math sucks :D), getveclen just figures out how long a vector is. what i want to do is use the built in vector maths to do vector operations, rather than using my own sketchy 2d versions. so that that mess looks like this.
if locked then
crosshair = target
elseif locking then
if crosshair-target:getMagnitude() > 1 then --i dont even know if thats leegal syntax, see i suck at this
direction = ma.normalizeVector(crosshair-target) -- im not sure what the name of the built in normalize function is
crosshair = crosshair + direction * ba.getFrametime(false) * 180 * sizefactors -- sizefactor is the x and y factors stored in a 2d vector object
else
locked = true
locking = false
end
else --we can transition to center now
if center-crosshair:getMagnitude() > 1 then
direction = ma.normalizeVector(crosshair-center)
crosshair = crosshair + direction * ba.getFrametime(false) * 120 * sizefactors
else
crosshair = center
end
end
as you see the code looks cleaner, i dont have to make sure i get my xes and ys in the right place. i dont have to re-invent the wheel by writing generic math functions for 2d. the purpose would be to make my hud script look less like a highschool comsci project, it would also make things easyer if i ever wanted to write hud asteroids. :D
ofcourse then again, i could use the 3d vector, and just set the z to 0.
*edit*
seems my scripting lightbulb lit up again. any chance we can get a number of bindable script commands in the controls editor. maybe like a dozen or so buttons and a couple axes to start. then have a function to retrieve the state of the bound keys/axes. this would allow for more player/script interaction. imput just seems like something missing from the scripting system.