- Posts
- 36
- Likes
- 119
Edit: updated at last.
Map porting:
Some may have noticed the threads I've made for ports. Here I hope to explain the method I use and possibly encourage others to do so. Any Jedi Academy or Jedi Outcast map may be ported to MB2 relatively easily, using entity modding. Steps for entity modding in general will follow at the bottom of this post. If you already know how, these are the requirements to porting a map:
General TFFA style: the bare minimum a map needs to work in MB2, aside from a correct .siege file (which is beyond the scope of this guide), are player spawns. You should have at least 16 info_player_siegeteam1 and 16 info_player_siegeteam2 entities in your map, appropriately placed. Some maps have 32 of each; technically, this is ideal, not because there are 64 player servers, but because there may be uneven teams.
Don't forget to add an info_player_intermission. Also, I've found some maps refuse to load with siegeteam spawns. Adding info_player_deathmatch spawns has solved the problem before, though I'm not sure why. Regardless, these are supported by MB2, but will not differentiate between teams.
Objectives: adding an objective will allow for a team to end the round by triggering a certain condition. Essentially, you add an info_siege_objective entity as the argument in a "target" parameter. Here are a few strategies: you can take advantage of existing triggers on a map and using them to trigger an objective. Note: you cannot add triggers through a simple entity mod, as they are both entities and brushes, and brushes cannot be manipulating with this technique (in theory, it is possible to edit brushes without decompiling by using a merge .bsp tool, but I haven't figured this out yet).
You can also use existing func_breakable things to trigger objectives - this is how I made the trench run map's reactor port trigger the objective; the mapper had already left in a mechanic to give points to people who shot the reactor port, so it was possible for me to adjust it to trigger the objective instead.
Another option is to use NPCs. If an NPC dies, it can trigger another entity. An example of this is re_mansion, where killing the infected at the end triggers the objective. Another example is the rancor on mb2_jabba, which triggers a script that unlocks the rancor pit's exit gate. The advantage of NPCs is that they can be added freely with an entity mod, although they may not fit the usual MB2 format of hacking terminals.
Some issues to consider: sometimes changing a trigger to require a long hack (adding a "usetime" parameter) doesn't work. In this case, an instant hack usually works, though it is jarring to have one of those trigger an objective.
Progressive siege: it is possible to convert a JKA style siege map into MB2's progressive siege format. I haven't done this yet, so I'll update this thread later when I know how to.
Entity modding guide - this is how you go about adding the aforementioned entities. My workflow:
Progressive siege:
What is progressive siege?
Mechanically, it is a method that sets up various groups of instructions (one group per stage) that apply different effects to a map. The current stage determines which group, and therefore which effects, are applied.
What are the possible effects?
Any. At the very minimum, different spawn points. But you can do anything: you can set different messages to be printed on the screen for each stage (Korriban prints "Stage 1 - Crystals" and "Stage 2 - Sarcophagus" on stages 1 and 2, respectively), you can spawn in NPCs and vehicles, you can disable certain hack points ("triggers"), etc. It is best to learn this from a more complete guide - jkhub " ". Recently, I began converting existing MB2 maps to progressive siege. On my mb2_ps_boc, in stage 1, Jedi must free Palpatine and in stage 2 they must escort him to the bridge. In this case, the same map areas are used for both stages. This presents certain problems, since nothing stops the stage 1 objective from being triggered on stage 2. There are some techniques you can use to get around this.
Converting an existing map to progressive siege:
There are a number of entities that are required. Copy these outright:
These are the ones used in mb2_ps_desert and mb2_ps_korriban. Unfortunately, they don't work as they are. I couldn't find out the precise mechanism used in those maps to swap between stages, so I came up with a work around. The only problem is the attacking team can't advance the stage by defeating the defenders - stages only swap with objectives and when defenders win. I'm not quite sure how to fix that. Still, for some purposes that might be ideal anyway. The method I use requires the following additional entities:
Essentially, they force a certain stage each time. If you want to get creative, you could also allow for stages to be skipped.
The most important thing to set up on PS is to apply different effects on each stage. The progressive siege check entities can do this, however, they cannot "target" anything directly. You need to have them execute a script file (.ibi). I decided to just use the korriban scripts for simplicity in my own edits (plus, I was worried that making a new script file would require people to download that file in order to join the server). These scripts follow the general rules. Korriban's stage 1 script file does a couple of things: it triggers "KorribanSpawn1Rebs", "KorribanSpawn1Imps" and "crystals".
Spawns: all spawns on a progressive siege map have "startoff" set to "1". This means that they will not work unless something triggers them. They also have lines "targetname" "KorribanSpawn1Rebs" and "target_scriptname" "KorribanSpawn1Rebs". When the script file is executed, it triggers "KorribanSpawn1Rebs" and activates the Rebel spawn points for stage 1. When stage 2 begins, all spawns are again reset and the stage 2 script triggers "KorribanSpawn2Rebs", enabling the new spawn points.
N.B. "targetname" is relevant for when one entity is set to trigger another entity. Say, entity A triggering entity B. You would have to set a field in entity A with "target" "entityB" and then add a field under entity B with "targetname "entityB". However, a script that triggers "entityB" will not work - you need to add a field to entity B with "target_scriptname" "entityB" in order for it to respond to the script.
N.B. 2 while experimenting, you might be tempted to have, say, an entity C with a different target name to its script target name. For example, "targetname" "entityc1" and "script_targetname" "entityC". I tried using this in one of my experiments, but it doesn't work - attempting to trigger "entityc1" does nothing in this case. So, "targetname" and "script_targetname" must be the same.
"crystals": it could be anything, really. You can name it anything and the script will attempt to trigger any entities with those characters as its name. In my BOC conversion, I used this to trigger some entities that I only wanted to be active in stage 1. However, just having "crystals" activating is very limiting when setting up entities. One option is to add more words being triggered to your script file. However, I've found that "target_counter" works wonders here.
"target_counter": you can set a "count" and a "target". "Count" is the number of times "target_counter" needs to be targeted in order to trigger the name in its "target" field. You could set "count" to "1" and then have "target" set to "stage1setting", for example. Like this you have another name being triggered exclusively in stage 1.
N.B. when something is triggered, like "crystals", there is no limit to the number of entities it can trigger. If you have 10 entities with the name "crystals", all will be activated. So having crystals trigger a counter still allows it to trigger other things.
A counter can be used to set up conditions. For example, I wanted to make sure that Palpatine's chair can only be used to end the round in stage 1. (I don't remember the names I used, so these are merely examples.) The chair normally triggers the objective entity indirectly through a counter - this is because it also disables the visual effect on the hand restraints. For simplicity, let's assume that hacking the chair immediately triggers "stage1end", an info_siege_objective, which is set to end the round in the .siege file. In order to restrict it to stage 1, you need to change the target from "stage1end" to "stage1counter". Create a "target_counter" with "targetname" set to "stage1counter" and "count" set to "2". Then, make sure that stage 1 triggers "stage1counter" at the start. In this way, the count reaches "2" with the chair hack. In stage 2, you can still hack the chair, but it will only bring the count to 1 - so it won't end the round again.
N.B. counters only work with triggers set to "trigger_once". "trigger_multiple" doesn't work because you can just hack it multiple times and raise the count arbitrarily. Fortunately, an entity mod allows you do name "trigger_multiple" to "trigger_once" without any issues.
Above, I mentioned that you can use a counter to add other triggers beyond just crystals. This is useful for exactly the above situation: if you only had crystals as an exclusive stage 1 trigger, you would have to set the chair hack to target crystals and the chair counter named crystals as well. That would be fine if you had nothing else on the map. However, you might want to, say, spawn an NPC and call it crystals. The chair hack would spawn that NPC, in that case. Since it ends the round on stage 1, that's fine - but on stage 2 it would be possible to spawn the NPC by hacking the chair! So, using counters to indirectly create new triggers from crystals is a much better solution.
The second part of a PS map is the .siege file. It's similar to a normal one. Use the siege files for mb2_ps_desert and mb2_ps_korriban as guidelines. Essentially, you need to set as final every objective that is supposed to end a round. The rest is mostly the same as regular .siege files.
Entity modding comments:
You can do basically anything with entity modding here. The main limitation is that you cannot add hack points (e.g. trigger_once, trigger_multiple" to a map, so you need to leverage existing ones. The only exception is you can freely add in a "trigger_always" (and, indeed, you need to, in order to set up the progressive siege checks)
Map porting:
Some may have noticed the threads I've made for ports. Here I hope to explain the method I use and possibly encourage others to do so. Any Jedi Academy or Jedi Outcast map may be ported to MB2 relatively easily, using entity modding. Steps for entity modding in general will follow at the bottom of this post. If you already know how, these are the requirements to porting a map:
General TFFA style: the bare minimum a map needs to work in MB2, aside from a correct .siege file (which is beyond the scope of this guide), are player spawns. You should have at least 16 info_player_siegeteam1 and 16 info_player_siegeteam2 entities in your map, appropriately placed. Some maps have 32 of each; technically, this is ideal, not because there are 64 player servers, but because there may be uneven teams.
Don't forget to add an info_player_intermission. Also, I've found some maps refuse to load with siegeteam spawns. Adding info_player_deathmatch spawns has solved the problem before, though I'm not sure why. Regardless, these are supported by MB2, but will not differentiate between teams.
Objectives: adding an objective will allow for a team to end the round by triggering a certain condition. Essentially, you add an info_siege_objective entity as the argument in a "target" parameter. Here are a few strategies: you can take advantage of existing triggers on a map and using them to trigger an objective. Note: you cannot add triggers through a simple entity mod, as they are both entities and brushes, and brushes cannot be manipulating with this technique (in theory, it is possible to edit brushes without decompiling by using a merge .bsp tool, but I haven't figured this out yet).
You can also use existing func_breakable things to trigger objectives - this is how I made the trench run map's reactor port trigger the objective; the mapper had already left in a mechanic to give points to people who shot the reactor port, so it was possible for me to adjust it to trigger the objective instead.
Another option is to use NPCs. If an NPC dies, it can trigger another entity. An example of this is re_mansion, where killing the infected at the end triggers the objective. Another example is the rancor on mb2_jabba, which triggers a script that unlocks the rancor pit's exit gate. The advantage of NPCs is that they can be added freely with an entity mod, although they may not fit the usual MB2 format of hacking terminals.
Some issues to consider: sometimes changing a trigger to require a long hack (adding a "usetime" parameter) doesn't work. In this case, an instant hack usually works, though it is jarring to have one of those trigger an objective.
Progressive siege: it is possible to convert a JKA style siege map into MB2's progressive siege format. I haven't done this yet, so I'll update this thread later when I know how to.
Entity modding guide - this is how you go about adding the aforementioned entities. My workflow:
- Open the map's .bsp file in a text editor. Personally, I use notepad++;
- To jump to the entity section, search (ctrl + f) for worldspawn. This is always at the start of the entity section, so it is an easy way to find it (otherwise, you might be scrolling for a while);
- Copy all entity data to an empty text file. The entity data will start with an "{" and end with another "}", with potentially over several hundred lines in between. The end one is easy to find, but the starting one can be annoying - sometimes, it isn't in line with the real start of the entities. It will be a bit above the worldspawn and at the end of the last line of the general bsp gibberish, so you will have to scroll all the way to the right to find it;
- Rename this file to the same as the map's bsp except with extension ".ent". So, if you wanted to entity mod mb2_jabba.bsp, you would want it to be mb2_jabba.ent;
- To actually entity swap things around, edit the ent file in your text editor. You can change existing entities or add new ones, though for fewer errors I recommend trying to keep new additions or reductions to a minimum. Also, they should, ideally, be placed near to other entities with similar coordinates. For example, if you want to disable an entity, it's better to change its classname to info_null (this will make it do nothing regardless of parameters) instead of deleting it outright;
- To insert the new entities into the .bsp file: place the .bsp to be altered and the .ent file in your netradiant directory. You should insert into it a .bat file (name it "ent-to-bsp.bat") with the following contents:
q3map2.exe -game ja -onlyents mb2_jabba.ent
- Run this file. It will overwrite the .bsp you placed with the edited one. You can test it now, either by packaging it into a .pk3 file under maps/ or by creating a folder in the MBII folder called "maps" and placing it in there. Note: if another .bsp of the same name exists in a .pk3 in the MBII folder, it will overwrite this one, so this wouldn't be suitable for modding existing maps
Sometimes there may be errors, e.g. lights broken, portals/doors all white. This can be fixed by changing the order of the entities around. For example, writing the new entities around other entities with close origins
Progressive siege:
What is progressive siege?
Mechanically, it is a method that sets up various groups of instructions (one group per stage) that apply different effects to a map. The current stage determines which group, and therefore which effects, are applied.
What are the possible effects?
Any. At the very minimum, different spawn points. But you can do anything: you can set different messages to be printed on the screen for each stage (Korriban prints "Stage 1 - Crystals" and "Stage 2 - Sarcophagus" on stages 1 and 2, respectively), you can spawn in NPCs and vehicles, you can disable certain hack points ("triggers"), etc. It is best to learn this from a more complete guide - jkhub " ". Recently, I began converting existing MB2 maps to progressive siege. On my mb2_ps_boc, in stage 1, Jedi must free Palpatine and in stage 2 they must escort him to the bridge. In this case, the same map areas are used for both stages. This presents certain problems, since nothing stops the stage 1 objective from being triggered on stage 2. There are some techniques you can use to get around this.
Converting an existing map to progressive siege:
There are a number of entities that are required. Copy these outright:
These are the ones used in mb2_ps_desert and mb2_ps_korriban. Unfortunately, they don't work as they are. I couldn't find out the precise mechanism used in those maps to swap between stages, so I came up with a work around. The only problem is the attacking team can't advance the stage by defeating the defenders - stages only swap with objectives and when defenders win. I'm not quite sure how to fix that. Still, for some purposes that might be ideal anyway. The method I use requires the following additional entities:
Essentially, they force a certain stage each time. If you want to get creative, you could also allow for stages to be skipped.
The most important thing to set up on PS is to apply different effects on each stage. The progressive siege check entities can do this, however, they cannot "target" anything directly. You need to have them execute a script file (.ibi). I decided to just use the korriban scripts for simplicity in my own edits (plus, I was worried that making a new script file would require people to download that file in order to join the server). These scripts follow the general rules. Korriban's stage 1 script file does a couple of things: it triggers "KorribanSpawn1Rebs", "KorribanSpawn1Imps" and "crystals".
Spawns: all spawns on a progressive siege map have "startoff" set to "1". This means that they will not work unless something triggers them. They also have lines "targetname" "KorribanSpawn1Rebs" and "target_scriptname" "KorribanSpawn1Rebs". When the script file is executed, it triggers "KorribanSpawn1Rebs" and activates the Rebel spawn points for stage 1. When stage 2 begins, all spawns are again reset and the stage 2 script triggers "KorribanSpawn2Rebs", enabling the new spawn points.
N.B. "targetname" is relevant for when one entity is set to trigger another entity. Say, entity A triggering entity B. You would have to set a field in entity A with "target" "entityB" and then add a field under entity B with "targetname "entityB". However, a script that triggers "entityB" will not work - you need to add a field to entity B with "target_scriptname" "entityB" in order for it to respond to the script.
N.B. 2 while experimenting, you might be tempted to have, say, an entity C with a different target name to its script target name. For example, "targetname" "entityc1" and "script_targetname" "entityC". I tried using this in one of my experiments, but it doesn't work - attempting to trigger "entityc1" does nothing in this case. So, "targetname" and "script_targetname" must be the same.
"crystals": it could be anything, really. You can name it anything and the script will attempt to trigger any entities with those characters as its name. In my BOC conversion, I used this to trigger some entities that I only wanted to be active in stage 1. However, just having "crystals" activating is very limiting when setting up entities. One option is to add more words being triggered to your script file. However, I've found that "target_counter" works wonders here.
"target_counter": you can set a "count" and a "target". "Count" is the number of times "target_counter" needs to be targeted in order to trigger the name in its "target" field. You could set "count" to "1" and then have "target" set to "stage1setting", for example. Like this you have another name being triggered exclusively in stage 1.
N.B. when something is triggered, like "crystals", there is no limit to the number of entities it can trigger. If you have 10 entities with the name "crystals", all will be activated. So having crystals trigger a counter still allows it to trigger other things.
A counter can be used to set up conditions. For example, I wanted to make sure that Palpatine's chair can only be used to end the round in stage 1. (I don't remember the names I used, so these are merely examples.) The chair normally triggers the objective entity indirectly through a counter - this is because it also disables the visual effect on the hand restraints. For simplicity, let's assume that hacking the chair immediately triggers "stage1end", an info_siege_objective, which is set to end the round in the .siege file. In order to restrict it to stage 1, you need to change the target from "stage1end" to "stage1counter". Create a "target_counter" with "targetname" set to "stage1counter" and "count" set to "2". Then, make sure that stage 1 triggers "stage1counter" at the start. In this way, the count reaches "2" with the chair hack. In stage 2, you can still hack the chair, but it will only bring the count to 1 - so it won't end the round again.
N.B. counters only work with triggers set to "trigger_once". "trigger_multiple" doesn't work because you can just hack it multiple times and raise the count arbitrarily. Fortunately, an entity mod allows you do name "trigger_multiple" to "trigger_once" without any issues.
Above, I mentioned that you can use a counter to add other triggers beyond just crystals. This is useful for exactly the above situation: if you only had crystals as an exclusive stage 1 trigger, you would have to set the chair hack to target crystals and the chair counter named crystals as well. That would be fine if you had nothing else on the map. However, you might want to, say, spawn an NPC and call it crystals. The chair hack would spawn that NPC, in that case. Since it ends the round on stage 1, that's fine - but on stage 2 it would be possible to spawn the NPC by hacking the chair! So, using counters to indirectly create new triggers from crystals is a much better solution.
The second part of a PS map is the .siege file. It's similar to a normal one. Use the siege files for mb2_ps_desert and mb2_ps_korriban as guidelines. Essentially, you need to set as final every objective that is supposed to end a round. The rest is mostly the same as regular .siege files.
Entity modding comments:
You can do basically anything with entity modding here. The main limitation is that you cannot add hack points (e.g. trigger_once, trigger_multiple" to a map, so you need to leverage existing ones. The only exception is you can freely add in a "trigger_always" (and, indeed, you need to, in order to set up the progressive siege checks)
Last edited: