dram 14 Posted June 18, 2013 Here is a link to the original discussion: http://forums.bistudio.com/showthread.php?156296-Take-On-Mars-New-BIS-Game/page15 ---------- Post added at 14:48 ---------- Previous post was at 14:40 ---------- Take on Mars looks great. Two questions: Can we land the Viking Lander from 1976? Also, can you explain a bit more about the "run your own space program" part of the game (i.e budgeting and launching probes)? Thanks! All of our vehicles are based on real vehicles, but made with customizable slots. This means that the large rover (similar to Curiosity) has many slots on top where you can mount instruments, antennas etc. The Space Program has you starting with a small budget, launching your first lander to Mars. This lander has a low quality camera, to replicate the feeling of getting the first images of Mars. You then continue to improve your technology as you progress through the various missions, which consist of scientific analyses, exploration, and taking photos. For each mission you send a new vehicle, or, assign it to a vehicle already on the surface nearby, that can complete the mission. Thus, reusing vehicles for new missions is also possible. As for vehicle customization, there is a whole section in the main control room where you can construct various setups (another section is used for assigning missions etc). The vehicle you construct may be tested in the space agency's "Mars Yard" (inspired by the one at JPL), and you can drive it around just like you would later on the surface of Mars. There are no consequences for testing, it is used to test whether the setup you have assembled is usable (for example if you put a drill on the top of a vehicle, it will be quite useless). You can save this as a preset and send it to Mars thereafter. Alternatively, you may start a new mission, assign a pre-defined preset, and customize that. I expect more questions in this regard, so feel free to ask. Share this post Link to post Share on other sites
maddogx 13 Posted June 18, 2013 (edited) Some questions: 1. How many areas/maps will be available at launch and how large are they? (Individually.) Answered here. Three terrains, 16km² (4x4km) each. :) 2. What is the theoretical upper limit of map sizes in the engine? Does it support streaming/paging for large terrains? 3. How difficult will it be to create new maps? Is it possible from within the game or will there be separate modding tools? Edited June 18, 2013 by MadDogX Share this post Link to post Share on other sites
dram 14 Posted June 18, 2013 2. What is the theoretical upper limit of map sizes in the engine? Does it support streaming/paging for large terrains? Theoretically it depends on the grid size chosen and the super-texture resolution chosen, at present. I had tests with 16x16km terrain sizes which had one quarter of the terrain grid detail. Of course, you still have to manually fill that with objects, limiting it more by manpower than anything else. Streaming is not supported as of yet, but is planned. 3. How difficult will it be to create new maps? Is it possible from within the game or will there be separate modding tools? Creating new maps is actually very easy, but can be time consuming, especially with the level of detail we have chosen (due to the size of the small rover). Workbench (an editor that will be provided with the modding pack) will be available post-launch, allowing users to create custom maps, particle effects, view objects etc. We will make tutorial videos for all of these aspects progressively after launch. Otherwise, really useful features of Workbench are for example "painting objects", allowing for quick covering of large areas with trees, rocks etc. These can then be individually adjusted to suit if needed. Additionally, adjusting terrain height etc is also done with a similar brush. Share this post Link to post Share on other sites
LSK 1 Posted June 18, 2013 Is there going to be an Pre-Order Option? Is this digital distributed only? Share this post Link to post Share on other sites
dram 14 Posted June 18, 2013 Is there going to be an Pre-Order Option? We are sorting that at the moment, so I will be able to confirm soon. Is this digital distributed only? Yes, we would consider a limited count of boxed version if there was high interest. Share this post Link to post Share on other sites
Sealife 22 Posted June 18, 2013 Forgive my ignorance please I have a few questions that may be obvious but im a little narrow minded in terms of Rv4 centric for 13 years now The Engine for this will be the space game engine from Gaea mission ? In terms of the game play is it remotely managing and steering vehicles or are you able to play a character and drive these vehicles ? Will user made content be easy to add , I.E will there be an equivalent visitor and o2 tool or simply config mods ? Lastly if the map is merely 4km what happens when you reach the ends , is it space or water and is it instant death or simply infanite procedural of space /water Cheers Share this post Link to post Share on other sites
njmatrix 2 Posted June 18, 2013 I don't know if any of you have looked at Lunar Flight it is a great space explorer game and is only 9.99 on Steam so I am wonder what will Take On Mars be cost wise and what do they think they will accomplish that Lunar Flight hasn't? Will the specs be like TOH? More inportant will it run like TOH? I own TOH and don't even bother playing it because it is nearly unplayable framerate wise. Being it is basic terrain can we see a better running effort this time? Share this post Link to post Share on other sites
dram 14 Posted June 19, 2013 (edited) Hi, The Engine for this will be the space game engine from Gaea mission ? Yes, a very heavily modified, updated version of it, specifically in terms of modability. In terms of the game play is it remotely managing and steering vehicles or are you able to play a character and drive these vehicles ? You remotely control the vehicles from the mission control room. Character driving is something that would belong to a human settlement on Mars, but currently we are simulating rovers similar to Opportunity and Curiosity. Will user made content be easy to add , I.E will there be an equivalent visitor and o2 tool or simply config mods ? Yes, we will be releasing Workbench, a toolset allowing for particle editing, terrain editing (using something like a brush for editing terrain height, and "painting" trees, rocks etc), viewing objects, and so on. Additionally scenarios will be made using the in-game editor, where you may also try out the various vehicles as you please. Lastly if the map is merely 4km what happens when you reach the ends , is it space or water and is it instant death or simply infanite procedural of space /water We have a "border terrain" model which spans on enough so you do not see where the terrain ends, but no, we do not have procedural generated terrain into the distance, especially due to us using real satellite data. I don't know if any of you have looked at Lunar Flight it is a great space explorer game and is only 9.99 on Steam so I am wonder what will Take On Mars be cost wise and what do they think they will accomplish that Lunar Flight hasn't? Yes, Lunar Flight is a great game, I've played it and love it, along with Kerbal Space Program, and the free hardcore simulator, Orbiter. Take On Mars will be for 10 Euro, and is a completely different game. In the game you control rovers on mars, perform exploration tasks, analyses, photos, with every rock posing an obstacle. This is very different to Lunar Flight, which is more about flying, delivering cargo and so on. Will the specs be like TOH? More inportant will it run like TOH? I own TOH and don't even bother playing it because it is nearly unplayable framerate wise. Being it is basic terrain can we see a better running effort this time? The specs will be like those for Carrier Command: Gaea Mission, however, this version features much higher scalability. Specifically, you can adjust the physics simulation detail, for example, and you can also adjust 3D resolution scaling. That means that on a 1920x1080 monitor your GUI would work in that resolution, but the 3D render would work in 1920x1080 x 3D scale. Thus, you can double that if you have a powerful comp (and get ridiculous fidelity), or you can scale it down as well all the way to 0.1x. At this level, it ran on my really old and crap Fujitsu LifeBook (integrated graphics) at around 18 fps. Which in itself is very impressive. Thief 2 on the machine runs at around 25 fps, to give you an idea. Edited June 19, 2013 by Dram Share this post Link to post Share on other sites
mrcash2009 0 Posted June 19, 2013 Is this digital distributed only? More important is this Steam exclusive only? Or sprocket and other digital outlets with simple reg and key like arma2/OA? You mention specs for the Carrier Command game, could you state the exact minimum and recommended specs here at all? Just for the sake of stating it clear :) Share this post Link to post Share on other sites
chortles 263 Posted June 19, 2013 Here's hoping that this game is Steamworks... Share this post Link to post Share on other sites
maddogx 13 Posted June 19, 2013 Here's hoping that this game is Steamworks... Was already mentioned as a possibility during the E3 interview (in fact, I think he even said it would be ideal), but it was not confirmed as they are still evaluating it. Share this post Link to post Share on other sites
dram 14 Posted June 19, 2013 (edited) More important is this Steam exclusive only? Or sprocket and other digital outlets with simple reg and key like arma2/OA? It will be available on Sprocket as well, but will be a Steam key, so you will need to run on Steam. You mention specs for the Carrier Command game, could you state the exact minimum and recommended specs here at all? Just for the sake of stating it clear :) [TABLE=class: game_grid, width: 540] [TR] [TD=class: grid_sysreqs, bgcolor: #CCCCCC, colspan: 2]MINIMUM PC REQUIREMENTS[/TD] [/TR] [TR] [TD=class: grid_row_body]MINIMUM REQUIREMENTS[/TD] [/TR] [TR] [TD=class: grid_row_body]Windows XP/Vista/7[/TD] [/TR] [TR] [TD=class: grid_row_body]Intel Core 2 Duo 2.2GHz or AMD Dual-Core Athlon 2.5GHz[/TD] [/TR] [TR] [TD=class: grid_row_body]NVIDIA GeForce 8800GT with Shader Model 3 and 512MB VRAM[/TD] [/TR] [TR] [TD=class: grid_row_body]2GB RAM[/TD] [/TR] [TR] [TD=class: grid_row_body]4GB Free HDD Space[/TD] [/TR] [TR] [/TR] [TR] [TD=class: grid_row_body]9.0c DirectX [/TD] [/TR] [TR] [TD=class: grid_row_body] RECOMMENDED REQUIREMENTS[/TD] [/TR] [TR] [TD=class: grid_row_body]Windows 7[/TD] [/TR] [TR] [TD=class: grid_row_body]Intel Core i5 or AMD Athlon Phenom X4[/TD] [/TR] [TR] [TD=class: grid_row_body]NVIDIA GeForce GTX460 with Shader Model 3 and 1GB VRAM[/TD] [/TR] [TR] [TD=class: grid_row_body]4GB RAM[/TD] [/TR] [TR] [/TR] [TR] [TD=class: grid_row_body]9.0c DirectX[/TD] [/TR] [/TABLE] Was already mentioned as a possibility during the E3 interview (in fact, I think he even said it would be ideal), but it was not confirmed as they are still evaluating it. Yes, we are currently evaluating. We definitely want to have it present, as I know myself how convenient it is in terms of sharing content. As soon as more specific info regarding this is available, I will write it here. Edited June 19, 2013 by Dram Share this post Link to post Share on other sites
njmatrix 2 Posted June 19, 2013 I can live with the 10 Euro price that works for me and I think we can all live with those specs. I am looking forward to TOM actually. I thank you for answering the questions I had. I see this added to my steam collection rather nicely :) Share this post Link to post Share on other sites
dram 14 Posted June 19, 2013 I can live with the 10 Euro price that works for me and I think we can all live with those specs. I am looking forward to TOM actually. I thank you for answering the questions I had. I see this added to my steam collection rather nicely :) I'm glad you're looking forward to it. I'm hoping the modding will catch on and we see plenty of user content added. Share this post Link to post Share on other sites
Sealife 22 Posted June 19, 2013 Will it be possible to use FSM system to create some automony of ambient machines or other interesting things or this engine uses someother method than FSM ? Thanks for previous answer I already got my Euro ready , think that price is worth what I already learned and seen so far , great job , I hope some kind of MOD allows the long term future like DayZ for Arma 2 , or of course your own ideas allow it to get more life than TOH Share this post Link to post Share on other sites
maddogx 13 Posted June 19, 2013 One more from me: what scripting language does the game use, if any? (For scenarios and such.) Share this post Link to post Share on other sites
dram 14 Posted June 19, 2013 Will it be possible to use FSM system to create some automony of ambient machines or other interesting things or this engine uses someother method than FSM ?Thanks for previous answer I already got my Euro ready , think that price is worth what I already learned and seen so far , great job , I hope some kind of MOD allows the long term future like DayZ for Arma 2 , or of course your own ideas allow it to get more life than TOH This engine doesn't use the FSM system that ArmA has, though it is no problem to do the same things via script. As I mentioned before, the script allows really low-level access to the engine, theoretically allowing you to modify settings of the campaign in the script, as well as adjust individual parts of the vehicle, their position, damage and all those standard things, as well as create individual physics bodies, connect them via joints, spawn projectiles, mess with projectiles....the list goes on, and all of this can be done via script. The only issue is of course that as it allows such direct access, you can theoretically make a script which breaks things in the campaign, but this is far outweighed by the positive things that can be done with it. I can go into more detail about what's possible if you wish, but in general, anything game-wise can be changed directly from script. Also, scripts are not fps capped, and thus if complex enough and ridiculously un-optimized, can slow down the game. This is in contrast to ArmA, which ensure a fluid framerate by capping the script time, so some may see this as positive or negative. Both have their advantages and disadvantages. Share this post Link to post Share on other sites
EricM 0 Posted June 19, 2013 If this is a mod-friendly Carrier command engine, does this mean : - We could recreate something similar to Carrier command in terms of environnement (with water maybe, different skies...) - base building ? Scavenging ? research/upgrades? - Ennemy AI? - in a nutshell, with enough time and talent, could I make my own Battlezone-like game? Share this post Link to post Share on other sites
dram 14 Posted June 19, 2013 One more from me: what scripting language does the game use, if any? (For scenarios and such.) I guess the closest thing is C++. For example, below projectile.h, the file containing the projectile class definition: /**************************************************************************** * PROJECTILE ENTITY DEFINITION ***************************************************************************/ class Projectile extends TKOM_Entity { int FXIndex; float ImpactNextTime; float DeathTime; bool DeathByImpact; string ModelPath; string ContactPtcSnd; string PtcPath; Sound_Point fx_snd[PART_SOUNDS_MAX]; vector lastSimPos; ParticleEmitter ptc_emit; // Plays a particle effect, creates it if it does not exist void SetPTC(string ptcStr) { if (!ptc_emit) { ptc_emit = new ParticleEmitter; AddChild(this, ptc_emit, -1); SetOrigin(ptc_emit, ZeroVec); SetAngles(ptc_emit, ZeroVec); ptc_emit.Play(ptcStr); } } // Deletes the attached particle effect void DeletePTC() { if (ptc_emit) { RemoveChild(this, ptc_emit); delete ptc_emit; ptc_emit = NULL; } } // Stops a playing sound on the part void StopSnd(int sndIndex) { if (fx_snd[sndIndex]) { /*Sound_Point sndPt = fx_snd[sndIndex]; if (sndPt.attached) RemoveChild(this, sndPt);*/ delete fx_snd[sndIndex]; fx_snd[sndIndex] = NULL; } } // Stops all sounds void DeleteSnds() { for (int i = 0; i < PART_SOUNDS_MAX; i++) { StopSnd(i); } } // Plays a sound on the part void PlaySnd(int sndIndex, string sshader, int flags, float volume, float freq) { if (Snd_Global_Vol > 0 && Snd_Global_Freq > 0) { // Don't play sounds if global modulators are null Sound_Point sndPt = NULL; if (!fx_snd[sndIndex]) { sndPt = new Sound_Point(GetOrigin(this), false, sshader, flags, volume, freq); if (sndPt.snd_handle == -1) { Print(String("VEHICLE_PART - PlaySnd: Could not play sound '" + sshader + "'!!!")); delete sndPt; } else fx_snd[sndIndex] = sndPt; } if (fx_snd[sndIndex]) { sndPt = fx_snd[sndIndex]; sndPt.snd_vol = volume; sndPt.snd_freq = freq; if (sndPt.snd_shader != sshader) { StopSnd(sndIndex); PlaySnd(sndIndex, sshader, flags, volume, freq); } } } } // Plays a sound at a location void PlaySndAt(vector pos, string sshader, int flags, float volume, float freq) { if (Snd_Global_Vol > 0 && Snd_Global_Freq > 0) { // Don't play sounds if global modulators are null Sound_Point sndPt = new Sound_Point(pos, true, sshader, flags, volume, freq); if (sndPt.snd_handle == -1) { Print(String("VEHICLE_PART - PlaySndAt: Could not play sound '" + sshader + "'!!!")); delete sndPt; } } } // Returns an empty sound channel slot int GetFreeSoundChannel() { int result = -1; for (int i = 0; i < PART_SOUNDS_MAX; i++) { if (!fx_snd[i]) { result = i; i = PART_SOUNDS_MAX; } } return result; } // Updates sounds and their positions void UpdateSounds() { if (!noUpdate) { for (int i = 0; i < PART_SOUNDS_MAX; i++) { if (fx_snd[i]) { Sound_Point sndPt = fx_snd[i]; if (sndPt.snd_handle == -1) StopSnd(i); else SetOrigin(sndPt, GetOrigin(this)); } } } else DeleteSnds(); } void Projectile(vector mat[], float speed, owned string ptcSnd, owned string modelstr, owned string ptcFx, float mass, float lifeTime, bool impactDel) { lastSimPos = mat[3]; ptc_emit = NULL; FXIndex = -1; ImpactNextTime = GetMissionTime(1); if (lifeTime <= 0) DeathTime = -100; else DeathTime = lifeTime; if (impactDel) DeathByImpact = true; else DeathByImpact = false; ModelPath = modelstr; vobject model = GetObject(ModelPath); SetFlags(this, TFL_VISIBLE|TFL_ACTIVE|TFL_SOLID); SetObject(model); SetMatrix(this, mat); vector vel = mat[0] * speed; ContactPtcSnd = ptcSnd; if (ContactPtcSnd != "") FXIndex = CreateFXType(ContactPtcSnd); dBodyCreateDynamic(this, ZeroVec, 0xffffffff); dBodySetDamping(this, AirFriction_Global, AirFriction_Global); dBodySetSleepingTreshold(this, 0.15, 0.15); dBodySetMass(this, mass); SetEventMask(this, EV_SIMULATE|EV_CONTACT|EV_FRAME|EV_SOUNDEND); PtcPath = ptcFx; if (PtcPath != "") SetPTC(PtcPath); SetVelocity(this, vel); if (model) ReleaseObject(model, false); } void ~Projectile() { DeletePTC(); DeleteSnds(); ClearEventMask(this, EV_ALL); if (dBodyIsSet(this)) dBodyDestroy(this); } void UpdateAtmosphericDrag() { dBodySetDamping(this, AirFriction_Global, AirFriction_Global); } event private void EOnFrame(_entity other, int extra) { UpdateSounds(); UpdateAtmosphericDrag(); } private void EOnSimulate(_entity other, float dt) { if (lastSimPos == ZeroVec) lastSimPos = GetOrigin(this); // Handle back-tracing to look for missed collisions vector start = lastSimPos; vector end = GetOrigin(this); if (start != end) { _entity t_ent = NULL; float t_plane[4]; int t_surfparm; float result = TraceLineEx(start, end, ZeroVec, ZeroVec, t_ent, t_plane, 0, t_surfparm, TRACE_WORLD|TRACE_ENTS|TRACE_LINE|TRACE_ONLY_PHYSICS|TRACE_RAGDOLLS, NULL); //AddDShape(SHAPE_DIAMOND, ARGBF(255, 255, 0, 0), SS_NOOUTLINE, end - "1 1 1", end + "1 1 1"); if (result < 1 && t_ent && t_ent != this) SetOrigin(this, end); } lastSimPos = GetOrigin(this); // Under terrain, so set to correct pos float tHgt = lastSimPos[2] - GetTerrainHeight(lastSimPos); if (tHgt <= 0) { if (tHgt < 0) lastSimPos[2] = GetTerrainHeight(lastSimPos); else lastSimPos[2] = lastSimPos[2] + 1; SetOrigin(this, lastSimPos); lastSimPos = GetOrigin(this); } if (DeathTime > -100 && !noUpdate) { DeathTime -= dt; if (DeathTime <= 0) delete this; } } private void EOnContact(_entity other, Contact extra) { if (!noUpdate) { vector mins, maxs; GetBoundBox(this, mins, maxs); float PartDensity = dBodyGetMass(this) / VectorLength(maxs - mins); float ContactVel = VectorLength(dBodyGetVelocityAt(this, extra.Position)); if (dBodyIsSet(other)) ContactVel = VectorLength(dBodyGetVelocityAt(other, extra.Position) - dBodyGetVelocityAt(this, extra.Position)); float ContactImpulse = extra.Impulse * fabs(1 / PartDensity) + ContactVel * 0.5; int iLvl = 0; if (ContactImpulse >= PART_IMPACT_HEAVY) iLvl = 4; else { if (ContactImpulse >= PART_IMPACT_MEDIUM) iLvl = 3; else { if (ContactImpulse >= PART_IMPACT_LIGHT) iLvl = 2; else { if (ContactImpulse >= PART_IMPACT_SCRAPE) iLvl = 1; } } } Vehicle_FX fxEnt = NULL; if (FXIndex != -1) fxEnt = Vehicle_FXList[FXIndex]; if (fxEnt && GetMissionTime(1) >= ImpactNextTime && iLvl > 0) { string iPtc = ""; string iSnd = ""; string iSndFar = ""; float iVol = 1; float iVolFar = 1; float iDistFar = 3200; vector mat[4]; if (iLvl == 4) { ImpactNextTime = GetMissionTime(1) + frand(fxEnt.FX_Lng_Contact_Hvy * 0.9, fxEnt.FX_Lng_Contact_Hvy * 1.1); iSnd = fxEnt.FX_Snd_Contact_Hvy; iSndFar = fxEnt.FX_Snd_ContactFar_Hvy; iVol = fxEnt.FX_Vol_Contact_Hvy; iVolFar = fxEnt.FX_Vol_Contact_Hvy; iPtc = fxEnt.FX_Ptc_Contact_Hvy; iDistFar = fxEnt.FX_Dist_ContactFar_Hvy; } if (iLvl == 3) { ImpactNextTime = GetMissionTime(1) + frand(fxEnt.FX_Lng_Contact_Med * 0.9, fxEnt.FX_Lng_Contact_Med * 1.1); iSnd = fxEnt.FX_Snd_Contact_Med; iSndFar = fxEnt.FX_Snd_ContactFar_Med; iVol = fxEnt.FX_Vol_Contact_Med; iVolFar = fxEnt.FX_Vol_Contact_Med; iPtc = fxEnt.FX_Ptc_Contact_Med; iDistFar = fxEnt.FX_Dist_ContactFar_Med; } if (iLvl == 2) { ImpactNextTime = GetMissionTime(1) + frand(fxEnt.FX_Lng_Contact_Lgt * 0.9, fxEnt.FX_Lng_Contact_Lgt * 1.1); iSnd = fxEnt.FX_Snd_Contact_Lgt; iSndFar = fxEnt.FX_Snd_ContactFar_Lgt; iVol = fxEnt.FX_Vol_Contact_Lgt; iVolFar = fxEnt.FX_Vol_Contact_Lgt; iPtc = fxEnt.FX_Ptc_Contact_Lgt; iDistFar = fxEnt.FX_Dist_ContactFar_Lgt; } GetCamera(CurrentListenCam, mat); float dist = VectorLength(GetOrigin(this) - mat[3]); if (iLvl == 1) { if (dist <= PART_SCRAPE_MAXDIST && GetMissionTime(1) > Part_LastScrape) { if (ContactVel >= PART_SCRAPE_HEAVY) { Part_LastScrape = GetMissionTime(1) + frand(fxEnt.FX_Lng_Scrape_Hvy * 0.9, fxEnt.FX_Lng_Scrape_Hvy * 1.1); iSnd = fxEnt.FX_Snd_Scrape_Hvy; iVol = fxEnt.FX_Vol_Scrape_Hvy; iPtc = fxEnt.FX_Ptc_Scrape_Hvy; } else { if (ContactVel >= PART_SCRAPE_MEDIUM) { Part_LastScrape = GetMissionTime(1) + frand(fxEnt.FX_Lng_Scrape_Med * 0.9, fxEnt.FX_Lng_Scrape_Med * 1.1); iSnd = fxEnt.FX_Snd_Scrape_Med; iVol = fxEnt.FX_Vol_Scrape_Med; iPtc = fxEnt.FX_Ptc_Scrape_Med; } else { Part_LastScrape = GetMissionTime(1) + frand(fxEnt.FX_Lng_Scrape_Lgt * 0.9, fxEnt.FX_Lng_Scrape_Lgt * 1.1); iSnd = fxEnt.FX_Snd_Scrape_Lgt; iVol = fxEnt.FX_Vol_Scrape_Lgt; iPtc = fxEnt.FX_Ptc_Scrape_Lgt; } } } } GetMatrix4(this, mat); if (iSnd != "" && dist < iDistFar) PlaySndAt(mat[3], iSnd, SFX_ONCE|SFX_3D|SFX_DISCARDABLE, iVol, frand(0.9, 1.1)); if (iSndFar != "" && dist >= iDistFar) PlaySndAt(mat[3], iSndFar, SFX_ONCE|SFX_3D|SFX_DISCARDABLE, iVolFar, frand(0.9, 1.1)); if (iPtc != "") { vector up = extra.Normal; vector forward = mat[0]; vector aside = up * forward; VectorNormalize(aside); forward = aside * up; mat[0] = forward; mat[1] = aside; mat[2] = up; mat[3] = extra.Position; PlayParticleEffect(iPtc, mat); } } if (DeathByImpact) delete this; } } } /**************************************************************************** ***************************************************************************/ Share this post Link to post Share on other sites
Sealife 22 Posted June 19, 2013 Sounds great , thanks for informative answer I guessthe detail woukd be better in the form of a wiki entry so I wont trouble you with that at this stage ,as always believe most questions will come from the how do I format than the what can I do with this kind of game First thing I will be trying is replicate the beagle disaster of europe and UK attempt to land a rover on mars , I take it gravity etc is moddelled as it should ? Share this post Link to post Share on other sites
dram 14 Posted June 19, 2013 If this is a mod-friendly Carrier command engine, does this mean :- We could recreate something similar to Carrier command in terms of environnement (with water maybe, different skies...) - base building ? Scavenging ? research/upgrades? - Ennemy AI? - in a nutshell, with enough time and talent, could I make my own Battlezone-like game? Well what you're writing there is essentially a total conversion, and yes it would be possible. Every part of the game is accessible in scripts, so you could actually write a whole new game if you liked, but that would require editing the base files I guess. But specifically, environments with water will be possible as well as different skies (for example the planned Deimos addon). Base building and the likes are also possible if you took the time to write it. Essentially, you could do it sort of hack-wise by making a base vehicle that when selected runs a script that allows this type of gameplay, with a custom hud allowing buying of vehicles, buildings, setting them waypoints, and if you're a good scripter/programmer, some AI would be possible to write as well. Alternatively, the locations themselves can run scripts, so you could call it from there I guess. ---------- Post added at 19:15 ---------- Previous post was at 19:13 ---------- First thing I will be trying is replicate the beagle disaster of europe and UK attempt to land a rover on mars , I take it gravity etc is moddelled as it should ? Funny that, we do have a beagle model in there as well :) And yes, gravity is modelled correctly, and is defined in the location's config file (so can be set per location, along with longitude/latitude, air friction, gravity etc etc). Share this post Link to post Share on other sites
purepassion 22 Posted June 19, 2013 Is the space agency called DramSpace? Oh and is there a possibility to get your hands on the wallpaper which the E3 machines were using? Share this post Link to post Share on other sites
dram 14 Posted June 19, 2013 Is the space agency called DramSpace? That was a joke by some of our team :) It's actually MARS-X: Multinational Agency for Robotic Space eXploration. Oh and is there a possibility to get your hands on the wallpaper which the E3 machines were using? Hmm, I'm surprised they weren't on the site. They should be available tomorrow on the page, I'll post on the forums with them. ---------- Post added at 22:10 ---------- Previous post was at 22:06 ---------- ...mod-friendly Carrier command engine... Just to re-iterate, the whole game is written entirely in script, save for a few menu options and closed source parts (renderer, sound engine etc, as well as input controller), so if one wanted to make a completely different game using the absolute base (that is remove all TOM assets and put one's own), then that is also possible. I would warn though that such an option is obviously extremely time consuming (essentially making a game from scratch), nevertheless, it is possible. Share this post Link to post Share on other sites
maddogx 13 Posted June 20, 2013 One more from me: what scripting language does the game use, if any? (For scenarios and such.) I guess the closest thing is C++. (...) Essentially, you could do it sort of hack-wise by making a base vehicle that when selected runs a script that allows this type of gameplay, (...) First of all, thanks for the extremely detailed answer (including example config!), but I think you mistook my meaning. :) My question was about the in-game scripting environment (like SQF in Arma), e.g. which scripting language is used and how it works. When you say "run a script that allows this type of gameplay", I'm sure you don't mean people have to write C++ code, right? ;) Share this post Link to post Share on other sites
dram 14 Posted June 20, 2013 First of all, thanks for the extremely detailed answer (including example config!), but I think you mistook my meaning. :)My question was about the in-game scripting environment (like SQF in Arma), e.g. which scripting language is used and how it works. When you say "run a script that allows this type of gameplay", I'm sure you don't mean people have to write C++ code, right? ;) Ah, I misunderstood. In any case, in game scripts are the same format. It allows compiling even in game, meaning you can edit a script and have it be recompiled while in game (using script modules). There are of course low-level functions and high-level functions. The low level ones being things like I mentioned, allowing creating physics objects etc etc etc, while high level functions being things like BreakJoint(int jointNum), which is a function for the vehicle that tells it to break a specific joint (and in the function it handles the low-level deleting of the joint and everything around it). Obviously that can startle people at first, that it is essentially similar to c++, however it is extremely powerful, and very performance efficient, hence the choice for this. Like I said, it's not exactly c++, but think of it more like a simplified version of it. Here is the in-game script that controls the rover movement, for example: /**************************************************************************** * 6-WHEELED ROVER CONTROLLER ***************************************************************************/ void Controller_OnSim(Vehicle_Controller controller) { Vehicle_Handler vehicle = controller.ownerVehicle; int i1 = 0; int i2 = 0; int i3 = 0; int i4 = 0; bool b1 = false; bool b2 = false; bool b3 = false; bool b4 = false; bool b5 = false; bool b6 = false; bool b7 = false; float f1 = 0; float f2 = 0; float f3 = 0; float f4 = 0; float f5 = 0; Vehicle_Part e1 = NULL; vector v1 = ZeroVec; vector v2 = ZeroVec; vector v3 = ZeroVec; vector v4 = ZeroVec; vector v5 = ZeroVec; vector v6 = ZeroVec; vector v7 = ZeroVec; Vehicle_FX fxEnt = NULL; /*b1 = false; b2 = false; if (parts_ents[CurrentPriPart] && parts_types[CurrentPriPart] == "Rover6") b1 = true; if (parts_ents[CurrentSecPart] && parts_types[CurrentSecPart] == "Rover6") b2 = true; if (b1 || b2) {*/ // Get wheel offsets center for (i1 = 0; i1 < vehicle.parts_num; i1++) { if (vehicle.parts_ents[i1] && vehicle.parts_types[i1] == "Wheel") { if (vehicle.parts_pos[i1][0] > v2[0]) v2[0] = vehicle.parts_pos[i1][0]; if (vehicle.parts_pos[i1][0] < v2[1]) v2[1] = vehicle.parts_pos[i1][0]; } if (vehicle.parts_ents[i1] && vehicle.parts_types[i1] == "Steering") { if (vehicle.parts_pos[i1][0] > v3[0]) v3[0] = vehicle.parts_pos[i1][0]; if (vehicle.parts_pos[i1][0] < v3[1]) v3[1] = vehicle.parts_pos[i1][0]; } } // Update wheel status indicators if selected if (vehicle.isSelected) { for (i1 = 0; i1 < vehicle.parts_num; i1++) { if (vehicle.parts_ents[i1] && vehicle.parts_types[i1] == "Wheel") { e1 = vehicle.parts_ents[i1]; v1 = vehicle.parts_pos[i1]; i4 = -1; // Get the position of the wheel to determine which HUD indicator applies if (v1[1] > 0 && v1[0] == v2[0]) // Left-Front i4 = 0; if (v1[1] > 0 && v1[0] < v2[0] - 1 && v1[0] > v2[1] + 1) // Left-Middle i4 = 1; if (v1[1] > 0 && v1[0] == v2[1]) // Left-Back i4 = 2; if (v1[1] < 0 && v1[0] == v2[0]) // Right-Front i4 = 3; if (v1[1] < 0 && v1[0] < v2[0] - 1 && v1[0] > v2[1] + 1) // Right-Middle i4 = 4; if (v1[1] < 0 && v1[0] == v2[1]) // Right-Back i4 = 5; if (i4 >= 0 && vehicle.CheckPartConnect(i1, 0)) { if (e1.GenVec[0] < 1) { // Not jammed vehicle.stat_state[i4] = 0; // Set status indicator state to Working } else { vehicle.stat_state[i4] = 1; // Set status indicator state to Malfunction } } else { if (i4 >= 0) vehicle.stat_state[i4] = 2; // Set status indicator state to Destroyed } } } } f2 = 0; f3 = 0; b1 = false; b2 = false; if (vehicle.parts_ents[vehicle.CurrentPriPart] && vehicle.parts_types[vehicle.CurrentPriPart] == "Rover6") b1 = true; if (vehicle.parts_ents[vehicle.CurrentSecPart] && vehicle.parts_types[vehicle.CurrentSecPart] == "Rover6") b2 = true; if (b1 && b2) { f2 = vehicle.input_arc_pri0; f3 = vehicle.input_arc_pri1; if (fabs(vehicle.input_arc_sec0) > fabs(f2)) f2 = vehicle.input_arc_sec0; if (fabs(vehicle.input_arc_sec1) > fabs(f3)) f3 = vehicle.input_arc_sec1; } else { if (b1) { f2 = vehicle.input_arc_pri0; f3 = vehicle.input_arc_pri1; } if (b2) { f2 = vehicle.input_arc_sec0; f3 = vehicle.input_arc_sec1; } } b4 = true; // Whether to allow wheel spin b5 = true; // Whether to allow steering b6 = false; // Whether to force on-spot steering b7 = true; // Whether to allow gripping v4 = "-9 -9 -9"; // Left wheels joint num (front, middle, back) v5 = "-9 -9 -9"; // Right wheels joint num (front, middle, back) v6 = "-9 -9 -9"; // Left steering joint num (front, back) v7 = "-9 -9 -9"; // Right steering joint num (front, back) if (!vehicle.SystemsActivated) // Disallow gripping if vehicle systems are not online b7 = false; // Run through and get joint numbers for (i1 = 0; i1 < vehicle.joints_num; i1++) { if (vehicle.joints_ents[i1]) { if (vehicle.joints_type[i1] == JOINT_MOTOR || vehicle.joints_type[i1] == JOINT_TMOTOR) { i2 = vehicle.joints_part2[i1]; if (vehicle.parts_ents[i2]) { e1 = vehicle.parts_ents[i2]; if (vehicle.parts_types[i2] == "Wheel" && vehicle.CheckPartConnect(i2, 0)) { v1 = vehicle.parts_pos[i2]; if (v1[1] > 0 && v1[0] == v2[0]) // Left-Front v4[0] = fabs(i1); if (v1[1] > 0 && v1[0] < v2[0] - 1 && v1[0] > v2[1] + 1) // Left-Middle v4[1] = fabs(i1); if (v1[1] > 0 && v1[0] == v2[1]) // Left-Back v4[2] = fabs(i1); if (v1[1] < 0 && v1[0] == v2[0]) // Right-Front v5[0] = fabs(i1); if (v1[1] < 0 && v1[0] < v2[0] - 1 && v1[0] > v2[1] + 1) // Right-Middle v5[1] = fabs(i1); if (v1[1] < 0 && v1[0] == v2[1]) // Right-Back v5[2] = fabs(i1); } if (vehicle.parts_types[i2] == "Steering" && vehicle.CheckPartConnect(i2, 0)) { v1 = vehicle.parts_pos[i2]; if (v1[1] > 0 && v1[0] == v3[0]) // Left-Front v6[0] = fabs(i1); if (v1[1] > 0 && v1[0] == v3[1]) // Left-Back v6[2] = fabs(i1); if (v1[1] < 0 && v1[0] == v3[0]) // Right-Front v7[0] = fabs(i1); if (v1[1] < 0 && v1[0] == v3[1]) // Right-Back v7[2] = fabs(i1); } } } } } // Get spin rates for (i1 = 0; i1 < 3; i1++) { if (v4[i1] != -9) { i2 = floor(v4[i1]); i2 = vehicle.joints_part2[i2]; e1 = vehicle.parts_ents[i2]; f4 = e1.GenVec[2]; v4[i1] = f4; } if (v5[i1] != -9) { i2 = floor(v5[i1]); i2 = vehicle.joints_part2[i2]; e1 = vehicle.parts_ents[i2]; f4 = e1.GenVec[2]; v5[i1] = f4; } if (v4[i1] == -9 && v5[i1] == -9) { if (f2 == 0 && f3 != 0) { // Turning on spot v4[i1] = 1; v5[i1] = -1; } else { v4[i1] = 0; v5[i1] = 0; } } else { if (v4[i1] == -9) { if (f2 == 0 && f3 != 0) // Turning on spot v4[i1] = v5[i1] * -1; else v4[i1] = v5[i1]; } if (v5[i1] == -9) { if (f2 == 0 && f3 != 0) // Turning on spot v5[i1] = v4[i1] * -1; else v5[i1] = v4[i1]; } } } // Get turn angles for (i1 = 0; i1 < 3; i1++) { if (v6[i1] != -9) { i2 = floor(v6[i1]); i2 = vehicle.joints_part2[i2]; e1 = vehicle.parts_ents[i2]; f4 = e1.GenVec[2]; v6[i1] = f4; } if (v7[i1] != -9) { i2 = floor(v7[i1]); i2 = vehicle.joints_part2[i2]; e1 = vehicle.parts_ents[i2]; f4 = e1.GenVec[2]; v7[i1] = f4; } if (v6[i1] == -9 && v7[i1] == -9) { if (f2 == 0 && f3 != 0) { // Turning on spot v6[i1] = -1; v7[i1] = 1; } else { v6[i1] = 0; v7[i1] = 0; } } else { if (v6[i1] == -9) { if (f2 == 0 && f3 != 0) // Turning on spot v6[i1] = v7[i1] * -1; else v6[i1] = v7[i1]; } if (v7[i1] == -9) { if (f2 == 0 && f3 != 0) // Turning on spot v7[i1] = v6[i1] * -1; else v7[i1] = v6[i1]; } } } for (i1 = 0; i1 < 3; i1++) { // Turning on spot if (f2 == 0 && f3 != 0) { f1 = v4[i1] + v5[i1]; f4 = fabs(v6[i1]) + fabs(v7[i1]); if (fabs(f1) > 0) { // Wheels spinning in same direction, so allow them to stop b4 = false; // Disallow spin b5 = false; // Disallow turning } if (f4 < 2) // Wheels not fully turned yet, so allow them to turn b4 = false; // Disallow spin } // Normal driving if (f2 != 0) { f1 = v4[i1] - v5[i1]; f4 = v6[i1] - v7[i1]; if (fabs(f4) > 0 && fabs(f1) == 0) // Wheels turned in opposing directions, so allow them to turn b4 = false; // Disallow spin if (fabs(f4) > 0 && fabs(f1) > 0) { // Wheels not stopped yet from on-spot turn, so let the wheels stop spinning first b4 = false; // Disallow spin b6 = true; // Force on-spot turn } } // Nothing if (f2 == 0 && f3 == 0) { f1 = fabs(v4[i1]) + fabs(v5[i1]); f4 = v6[i1] - v7[i1]; if (fabs(f4) > 0 && f1 > 0) // Wheels not stopped yet from on-spot turn, so let the wheels stop spinning first b6 = true; // Force on-spot turn } f1 = fabs(v4[i1]) + fabs(v5[i1]) + fabs(v6[i1]) + fabs(v7[i1]); if (f1 != 0) b7 = false; // Disallow gripping if moving or turning at all } // Now run through and set engine status etc for (i1 = 0; i1 < vehicle.joints_num; i1++) { if (vehicle.joints_ents[i1]) { if (vehicle.joints_type[i1] == JOINT_MOTOR || vehicle.joints_type[i1] == JOINT_TMOTOR) { i2 = vehicle.joints_part2[i1]; if (vehicle.parts_ents[i2]) { e1 = vehicle.parts_ents[i2]; if (vehicle.parts_types[i2] == "Wheel") { // ======================================= // =========== Wheel handling ============ // ======================================= /* For vehicle log: GenVec2[0] - if 1, logged a minor malfunction GenVec2[0] - if 2, logged a major malfunction */ f4 = e1.GenVec[0]; e1.GenVec[1] = e1.GenVec[1] + phys_FixedTick; if (e1.GenVec[1] >= 0.5 && vehicle.parts_damage[i2] > 0.25) { // Only check once per 1/2 second and only if damaged e1.GenVec[1] = 0; if (f2 != 0 || f3 != 0) { // Only check if the vehicle has input f1 = frand(0, 1); // If wheel not jammed, % chance of jamming relative to the damage if (f4 < 1 && f1 <= vehicle.parts_damage[i2] - 0.25 / 0.75) f4 = 1; else { // If wheel jammed, % chance of jamming permanently relative to the damage, and only above 0.6 damage if (f4 == 1 && vehicle.parts_damage[i2] > 0.6 && f1 <= vehicle.parts_damage[i2] - 0.6 / 0.4) f4 = 2; // If wheel jammed, % chance of unjamming relative to the damage if (f4 == 1 && f1 >= vehicle.parts_damage[i2] - 0.25 / 0.75) f4 = 0; } if (f4 == 0 && e1.GenVec[0] > 0) e1.GenVec[0] = 0; if (f4 == 1 && e1.GenVec[0] == 0) { e1.GenVec[0] = 1; vehicle.storage.AddLogEntry("#tkom_log_malfmin " + vehicle.parts_title[i2] + " " + itoa(vehicle.PartTypeGetNum(i2, vehicle.parts_types[i2]))); } if (f4 == 2 && e1.GenVec[0] != 2) { e1.GenVec[0] = 2; vehicle.storage.AddLogEntry("#tkom_log_malfmaj " + vehicle.parts_title[i2] + " " + itoa(vehicle.PartTypeGetNum(i2, vehicle.parts_types[i2]))); } e1.GenVec[0] = f4; } } b3 = false; if (vehicle.CheckPartConnect(i2, 0)) { b3 = true; e1.SetGrip(1.5, 2.5); } // Set power drainage if connected if (b3) { if (f2 == 0 && f3 != 0) vehicle.parts_pwrdrain[i2] = fabs(f3) * vehicle.joints_pwrdrain[i1]; else vehicle.parts_pwrdrain[i2] = fabs(f2) * vehicle.joints_pwrdrain[i1]; } else vehicle.parts_pwrdrain[i2] = 0; if (f4 < 1 && b3) { // Not jammed, connected f1 = f2; if (f2 == 0 && f3 != 0) { // Turning on spot f1 = f3; v1 = vehicle.parts_pos[i2]; if (v1[1] < 0) // Right side f1 *= -1; if (v1[0] < v2[0] - 1 && v1[0] > v2[1] + 1) // Middle f1 *= 0.5; } if (!b4) // Not allowed to spin f1 = 0; float maxSpeed = 0; if (g_Campaign) maxSpeed = g_Campaign.Scale_Speed * vehicle.joints_limits_lo[i1][1]; f5 = vehicle.joints_limits_hi[i1][1] / maxSpeed * phys_FixedTick; f4 = e1.GenVec[2]; // Get the current spin rate if (f1 < f4) { if (f1 > f4 - f5) f5 = f4 - f1; f4 -= f5; } if (f1 > f4) { if (f1 < f4 + f5) f5 = f1 - f4; f4 += f5; } e1.GenVec[2] = f4; f1 = f4; // Ungrip the part if it is gripped and is not allowed if (e1.Gripped && !b7) e1.Grip(false); // Awaken part if sleeping if (!dBodyIsActive(vehicle.parts_ents[i2]) && f1 != 0) dBodyActive(vehicle.parts_ents[i2], true); if (f1 != 0) { fxEnt = NULL; if (e1.FXIndex != -1) fxEnt = Vehicle_FXList[e1.FXIndex]; if (fxEnt && fxEnt.FX_Snd_Engine != "") e1.PlaySnd(PART_SOUNDS_EXTCHNL1, fxEnt.FX_Snd_Engine, SFX_3D, fxEnt.FX_Vol_Engine * fabs(f1), 0.2 * fabs(f1) + 1.2); } else e1.StopSnd(PART_SOUNDS_EXTCHNL1); if (e1.Gripped) dJointSliderSetAngularMotor(vehicle.joints_ents[i1], 0, 0); else dJointSliderSetAngularMotor(vehicle.joints_ents[i1], f1 * maxSpeed, vehicle.joints_limits_lo[i1][2]); } else { e1.StopSnd(PART_SOUNDS_EXTCHNL1); dJointSliderSetAngularMotor(vehicle.joints_ents[i1], 0, vehicle.joints_limits_lo[i1][2]); } // ======================================= } if (vehicle.parts_types[i2] == "Steering") { // ======================================= // ========== Steering handling ========== // ======================================= if (vehicle.CheckPartConnect(i2, 0)) { // Connected vehicle.parts_pwrdrain[i2] = fabs(f3) * vehicle.joints_pwrdrain[i1]; // Set power drainage f1 = f3; v1 = vehicle.parts_pos[i2]; if (f2 == 0 || b6) { if (f1 != 0 || b6) f1 = 1; if (v1[1] < 0) f1 *= -1; } if (v1[0] > 0) f1 *= -1; if (!b5 && !b6) // Not allowed to turn, but not forced to turn on-spot f1 = 0; f5 = vehicle.joints_limits_lo[i1][2] * 0.25 * phys_FixedTick; f4 = e1.GenVec[2]; // Get the current turn if (b5 || b6) { // Not allowed to turn, but not forced to turn on-spot if (f1 < f4) { if (f1 > f4 - f5) f5 = f4 - f1; f4 -= f5; } if (f1 > f4) { if (f1 < f4 + f5) f5 = f1 - f4; f4 += f5; } } float tDiff = sin(fabs(f4 - f1) * 180 * DEG2RAD); e1.GenVec[2] = f4; f1 = f4; // Awaken part if sleeping if (!dBodyIsActive(vehicle.parts_ents[i2]) && f1 != 0) dBodyActive(vehicle.parts_ents[i2], true); if (tDiff != 0) { fxEnt = NULL; if (e1.FXIndex != -1) fxEnt = Vehicle_FXList[e1.FXIndex]; if (fxEnt && fxEnt.FX_Snd_Engine != "") e1.PlaySnd(PART_SOUNDS_EXTCHNL1, fxEnt.FX_Snd_Engine, SFX_3D, fxEnt.FX_Vol_Engine * fabs(tDiff) + 0.1, 0.3 * fabs(tDiff) + 0.9); } else e1.StopSnd(PART_SOUNDS_EXTCHNL1); dJointHingeSetMotorTargetAngle(vehicle.joints_ents[i1], f1 * 50 * DEG2RAD, vehicle.joints_limits_lo[i1][1], vehicle.joints_limits_lo[i1][2]); } else { e1.StopSnd(PART_SOUNDS_EXTCHNL1); vehicle.parts_pwrdrain[i2] = 0; // Clear power drainage dJointHingeSetMotorTargetAngle(vehicle.joints_ents[i1], 0, vehicle.joints_limits_lo[i1][1], vehicle.joints_limits_lo[i1][2]); } // ======================================= } if (vehicle.parts_types[i2] == "Suspension") dJointHingeSetMotorTargetAngle(vehicle.joints_ents[i1], 0, vehicle.joints_limits_lo[i1][1], vehicle.joints_limits_lo[i1][2]); } } } } //} // Enable wheel tracks only if main part is rover6 and only for attached wheels if (vehicle.parts_types[0] == "Rover6") { for (i1 = 0; i1 < vehicle.parts_num; i1++) { if (vehicle.parts_ents[i1] && vehicle.parts_types[i1] == "Wheel") { e1 = vehicle.parts_ents[i1]; if (vehicle.CheckPartConnect(i1, 0)) e1.EnableTracks(true); else e1.EnableTracks(false); } } } } /**************************************************************************** ***************************************************************************/ Share this post Link to post Share on other sites