Jump to content

R&D to Increase Squad Size


Beknatok

Recommended Posts

Wow, thank you! :)

 

I will try poking around with the timing during the coming weekend.

 

I don't think I personally will try any bigger modding than that in the action scrips. At least not any time soon and also since you have already addressed anything I can think of that was in need of improvement :cool:

 

However I'm pretty sure the additional information will come in very handy sooner or later.

Link to comment
Share on other sites

  • Replies 429
  • Created
  • Last Reply

Top Posters In This Topic

Changing the initial delay was simple enough as it was only a single byte edit. (I removed it completely as I figure the fade-in effect itself is delay enough).

Replace:
96 1c 00 08 0c 07 03 00 00 00 08 0a 04 01 00 61 6e 69 6d 61 74 65 43 6f 6d 70 6c 65 74 65 00
With:
96 1c 00 08 0c 07 00 00 00 00 08 0a 04 01 00 61 6e 69 6d 61 74 65 43 6f 6d 70 6c 65 74 65 00

But figuring out how to remove the delay before fade-out proved to be a tad overwhelming :sad:

 

Sure I got the basic principle behind it all... Use the p-code-editor to modify and if the resulting size is different, use the padding string to compensate...

 

So I figure this:

      this.txtItem1.animateComplete = function()
      {
            caurina.transitions.Tweener.addTween(this.textField,{transition:"linear",onComplete:mx.utils.Delegate.create(this,function()
            {
                  this.textField._y = 0;
            }
            ),time:XComScrollingTextField.FADE_TIME,delay:XComScrollingTextField.REPEAT_DELAY,_alpha:0});
            caurina.transitions.Tweener.addTween(this.textField,{transition:"linear",onComplete:mx.utils.Delegate.create(this,this.resetScroll),time:XComScrollingTextField.FADE_TIME,delay:XComScrollingTextField.REPEAT_DELAY + XComScrollingTextField.FADE_TIME,_alpha:100});
      };

should probably be changed to something like this:

...
            ),time:XComScrollingTextField.FADE_TIME,delay:0,_alpha:0});

or possibly something like this:
...
            caurina.transitions.Tweener.addTween(this.textField,{transition:"linear",onComplete:mx.utils.Delegate.create(this,this.resetScroll),time:XComScrollingTextField.FADE_TIME,delay:0 + XComScrollingTextField.FADE_TIME,_alpha:100});
      };

And then when the p-code-editor shows things like this:

GetMember
; 96 11 00 00 61 6e 69 6d 61 74 65 43 6f 6d 70 6c 65 74 65 00
Push "animateComplete"; 8e 08 00 00 00 00 07 29 00 3b 01

DefineFunction2 "" 0 7 false false true false true false false true false  {
; 96 11 00 00 5f 61 6c 70 68 61 00 07 00 00 00 00 08 0c 08 0d
Push "_alpha" 0 "delay" "XComScrollingTextField"; 1c

GetVariable
; 96 02 00 08 0e
Push "REPEAT_DELAY"; 4e

GetMember
; 96 04 00 08 0b 08 0d
Push "time" "XComScrollingTextField"; 1c

Then my head only hurts...

Link to comment
Share on other sites

Installation instruction

  1. Download and install (unzip) toolboks http://xcom.nexusmods.com/mods/79//?
  2. Download and unzip this file into the Custom Mods folder (inside the folder where you installed toolboks) http://forums.nexusmods.com/index.php?app=core&module=attach&section=attach&attach_id=35090
  3. Open toolboks and use the Custom Mods tab to install Increased_Squad_Size_v0_92.txt
  4. Optionally edit the last line in Increased_Squad_Size_v0_92.txt and repeat step 3 to change the number of soldiers (Vanilla seting is SkyRanger capacity = 4)
Link to comment
Share on other sites

Awesome I got it working with no problems. Just wondering one thing that might seem a little silly now. Is there a way I can increase the alien spawns as well? lol. I'm playing with the long war mod too so that helps but I can't help but feel even on impossible iron man that this amount of troops will upset the balance too much. If anyone here knows or is using a good mod to increase the enemy spawns or difficulty let me know.

 

But seriously good work whoever worked on this, it really is bad ass to have this many people on the field.

Link to comment
Share on other sites

Does someone think it's feasible to reserve an extra squad slot specifically to SHIVs?

During normal gameplay, training of soldiers is essential and makes you typically reject SHIVs; at least I feel that way. The idea is to have always one SHIV in the team as addition to the 4-6 human soldiers to avoid this dilemma.

 

The specific "Add SHIV" slot would need to pop up an alternative soldier list. This list only contains soldiers that are checked for SHIV gear, like eItem_SHIVDeck_I.

Link to comment
Share on other sites

I have used this mod for my Long War exp.(1.92) so that i have 7 (6 soldiers + 1 shiv) so i have 6 pawns and 1 without(shiv) aand it works great :)

 

Yes that could be and excellent idea, but think that would require a bit of recoding :/

 

On a side-note .. tried it with 12 soldiers on beta 2 (with tired mechanics) and Boy was that tiresome, having to re-equip all the men for missions. lol ..

 

Anyways .. you guys Rock !! :D keep up the good work

Link to comment
Share on other sites

Does someone think it's feasible to reserve an extra squad slot specifically to SHIVs?

During normal gameplay, training of soldiers is essential and makes you typically reject SHIVs; at least I feel that way. The idea is to have always one SHIV in the team as addition to the 4-6 human soldiers to avoid this dilemma.

 

The specific "Add SHIV" slot would need to pop up an alternative soldier list. This list only contains soldiers that are checked for SHIV gear, like eItem_SHIVDeck_I.

The last slot(s) represent riding on the outside like an astromech? :smile:

 

I guess an alternative way to do it would be to replace the RemainingPromotionsInSquad check/dialogue with a check that there are not too many human soldiers aboard and simply refuse to launch if that is the case.

That way there would be no need to modify slot functionality and to verify that SHIV-only slots were not autopopulated with humans by the game itself.

 

With some luck I could then also repurpose the entire confirmation dialogue to "Please confirm that soldier should be assigned to random class X" upon promotions. Which would be something I want a lot more than a warning that I have failed on debrief, loadout and anytime between, to promote my soldiers.

Link to comment
Share on other sites

But figuring out how to remove the delay before fade-out proved to be a tad overwhelming :sad:

Reading the disassembled byte code can be a little confusing at fist, but if you find out some underlying rules it starts to make sense. The basic principle behind it is the operand stack - every line of byte code either places elements onto or removes elements from the top of the stack for various purposes. As such the order in which stuff is set up in byte code appears somewhat backwards, e.g. function parameters are often defined in reverse order before the actual function call.

 

A few basic examples, first storing a value in a local register and doing some operations on it. Registers can be thought of as a kind of a local variable with no name specified; register1 always refers to the class instance itself (e.g. this) while, depending on how the enclosing function is defined register2 may refer to the immediate superclass of the current class instance (e.g. super). Be aware that, as with local variables in UnrealScript, they may be shared among functions that call each other which can lead to problems.

 

 

// simple variable assignment
// var _loc3_ = 5;
Push 5			// push integer '5' onto stack
StoreRegister 3		// copy value of top stack element into register 3
Pop			// remove top element from stack

// variable assignment with simple arithmetic
// _loc3_ = _loc3_ + 8;
Push register3 8	// push value of register 3 and integer '8' onto stack (8 ends up on top)
Add2			// combine top 2 elements of stack into one by performing addition, order of operands is in reverse stack position order
StoreRegister 3		// store top element in register 3
Pop			// remove top element

// variable assignment with more complex arithmetic
// _loc3_ = 1 - 2 * 3 * (4 + 5) / 9;
Push 1 2 3		// push three integers onto stack
Multiply		// combine top two elements via multiplication (2*3)
Push 4 5		// push two more integer onto stack
Add2			// combine top two elements via addition (4+5)
Multiply		// combine top two elements via multiplication (2*3)*(4+5)
Push 9			// push another integer onto stack
Divide			// combine top two elements via division ((2*3)*(4+5))/9
Subtract		// combine top two elements via subtraction 1 - (((2*3)*(4+5))/9)
StoreRegister 3		// store top element in register 3
Pop			// remove top element

 

 

Next examples, getting/setting instance variables:

 

 

// simple instance variable assignment
// this._x = 5;
Push register1 "_x" 5	// push 'this', '_x' and integer '5' onto stack
SetMember		// combine top three stack elements, store value into instance variable, remove top element (no need for 'pop' here)
			// first (i.e. lowest stack position) element defines scope, second element defines instance variable name, third (i.e. top) element defines value

// chained instance variable assignment
// this.someChild._y = 10;
Push register1 "someChild"	// push 'this' (scope) and 'someChild' (instance variable name) onto stack
GetMember			// combine top two stack elements by getting reference to instance variable (top element) of scope (next lower element)
Push "_y" 10			// push '_y' (instance variable name) and integer 10 (value) onto stack
SetMember			// combine top three stack elements by assigning value to instance variable

// instance variable assignment using static class variables and arithmetic
// this._width = 100 - SomeClass.someProperty * 2;
Push register1 "_width" 100 "SomeClass"	// push some values onto stack
GetVariable				// use top element value to get reference to class (also used to access local variables defined via 'DefineLocal')
Push "someProperty"			// push element to be used as variable name onto stack
GetMember				// combine top two stack elements ('SomeClass' reference and 'someProperty' variable name)
Push 2					// push another integer onto stack
Multiply				// combine top two stack elements via multiplication (SomeClass.someProperty*2)
Subtract				// combine top two stack elements via subtraction (100-(SomeClass.someProperty*2))
SetMember				// combine top three stack elements by assigning value to instance variable

 

 

As you can see, the byte code primarily revolves around putting things onto the stack, removing some of them for performing operations on them and sometimes putting the combined results back onto the stack.

More examples, method calls and object instantiation:

 

 

// simple method call with two parameters
// this.someMethod(45,18);
Push	18		// push second parameter onto stack
	45		// push first parameter
	2		// push number of arguments
	register1	// push scope
	"someMethod"	// push method name
CallMethod		// call method, put a return value onto stack (even if the method doesn't specifically define one)
Pop			// remove top element from stack

// simple object instantiation without parameters
// var _loc4_ = {};
Push 0			// push number of object parameters
InitObject		// combine top elements of stack into object (no parameters were defined, so an empty object is returned)
StoreRegister 4		// copy top stack element into register 4
Pop			// remove top stack element

// object instantiation with parameters
// var _loc4_ = {foo:8,bar:5};
Push	"bar"		// push name of second parameter onto stack
	5		// value of second parameter
	"foo"		// name of first parameter
	8		// value of first parameter
	2		// number of parameters
InitObject		// combine top elements of stack into object
StoreRegister 4		// copy top stack element into register 4
Pop			// remove top stack element

// complex object instantiation
// this.someMember = {_x:SomeClass.X_PADDING,_y:this._height - 50};
Push	register1	// scope and variable name for final SetMember operation (this.someMember)
	"someMember"	
	"_y"		// second parameter of InitObject operation
	register1	// instance variable
	"_height"
GetMember		// get instance variable (this._height)
Push 50			// arithmetic operand
Subtract		// perform arithmetic (this._height - 50)
Push	"_x"		// first parameter of InitObject operation
	"SomeClass"	// class name
GetVariable		// get reference to class
Push "X_PADDING"	// class variable name
GetMember		// get property value of static class variable
Push 2			// number of parameters for InitObject operation
InitObject		// instantiate object
SetMember		// store result in instance variable (this.someMember = ...)

 

 

Next up are function definitions:

 

 

// define class instance method without parameters
// function myMethod()
// {
//	return 0;
// }
Push register2 "myMethod"	// method name, scope always seems to point to register 2 for class methods
DefineFunction2 "" 0 2 false false true false true false false true false {
// not sure about the values here, '0' seems to indicate number of parameters, '2' has something to do with the number of registers available, I think,
// booleans look different for functions that can access superclass
Push 0		// method body
Return
}
SetMember	// assign method to scope

// define class instance method with parameters and access to superclass
// function doStuff(param1, param2)
// {
//	return super.doMore(param1 + param2);
// }
Push register2 "doStuff"	// method name and class scope
DefineFunction2 "" 2 4 false false false true true false false true false 3 "param1" 4 "param2"  {
// note different booleans allowing access to superclass, final values define argument names and which local register they occupy
Push register3 register4	// method body
Add2
Push 1 register2 "doMore"
CallMethod
Return
}
SetMember	// assign method to scope

// define anonymous method and store it in instance variable
// this.deg2rad = function(angle)
// {
// 	return Math.PI * angle / 180.0;
// };
Push register1 "deg2rad"	// set up scope and variable name for SetMember operation
DefineFunction2 "" 1 3 false false true false true false false true false 3 "angle"  {
Push "Math"		// function body
GetVariable
Push "PI"
GetMember
Push register3
Multiply
Push 180.0
Divide
Return
}
SetMember		// assign function to scope

 

 

What's neat about ActionScript is that methods in themselves are instances of the Function class and as such can be easily swapped out for another, which is exactly what I did to essentially override methods like animateComplete() in the unit box class.

 

I suppose that covers about everything that's relevant to explaining how the vertical scrolling was implemented. As for general ActionScript byte code haxing there's still the matter of conditionals for flow control statements (i.e. if/else, while, switch) and ternary operators, both of which deal with jump offsets (which are much easier to handle here as thankfully JPEXS will auto-calculate them). I can go into details about that if anyone's interested :smile:

 

Now, let's dissect the part related to the fade-out:

 

Wall of text incoming:

Push register1 "txtItem1"	// scope of 'animateComplete' function instance
GetMember
Push "animateComplete"		// function instance name
DefineFunction2 "" 0 7 false false true false true false false true false  {
				// body of 'animateComplete' function begins with defining second parameter of 'caurina.transitions.Tweener.addTween()' call
Push    "_alpha" 0		// target parameter for 'addTween()' call (fade alpha to zero)

	"delay"			// 'delay' parameter
	"XComScrollingTextField"
GetVariable
Push "REPEAT_DELAY"
GetMember			// get value of static XComScrollingTextField.REPEAT_DELAY variable

Push    "time"			// 'time' parameter
	"XComScrollingTextField"
GetVariable
Push "FADE_TIME"
GetMember			// get value of static XComScrollingTextField.FADE_TIME variable

Push "onComplete"		// 'onComplete' parameter, links to a function that is called after tweening ends
DefineFunction2 "" 0 2 false false true false true false false true false  {
Push register1 "textField"
GetMember
Push "_y" 0
SetMember			// reset '_y' variable to zero (reset y position to top)
}				// function as second argument of 'mx.utils.Delegate.create()' call
Push    register1 2		// 'this' as first argument, '2' = number of arguments
	"mx"			// chain together mx.utils.Delegate.create()
GetVariable
Push "utils"
GetMember
Push "Delegate"
GetMember
Push "create"
CallMethod

Push    "transition" "linear"	// 'transition' parameter, use 'linear' interpolation preset

	5			// number of elements for object instantiation
InitObject			// instantiate parameter object (second argument of 'addTween()' call)

Push register1 "textField"	// first argument of 'addTween()' call ('this.textField')
GetMember

Push    2			// number of arguments for 'addTween()'
	"caurina"		// chain together 'caurina.transitions.Tweener.addTween()'
GetVariable
Push "transitions"
GetMember
Push "Tweener"
GetMember
Push "addTween"
CallMethod			// call 'addTween()'
Pop				// drop return value

				// next section is associated with a second call to 'addTween()', begins with defining second argument
Push    "_alpha" 100		// target parameter of second 'addTween()' call

	"delay"			// 'delay' parameter
	"XComScrollingTextField"
GetVariable
Push "REPEAT_DELAY"
GetMember
Push "XComScrollingTextField"
GetVariable
Push "FADE_TIME"
GetMember
Add2

Push    "time"			// 'time' parameter
	"XComScrollingTextField"
GetVariable
Push "FADE_TIME"
GetMember

Push    "onComplete"		// 'onComplete' parameter
	register1 "resetScroll"
GetMember
Push    register1
	2
	"mx"
GetVariable
Push "utils"
GetMember
Push "Delegate"
GetMember
Push "create"
CallMethod			// 'mx.utils.Delegate.create(this,this.resetScroll)'

Push    "transition" "linear"	// 'transition' parameter

	5			// instantiate parameter object with '5' parameters (second argument of 'addTween()')
InitObject

Push register1 "textField"	// first argument of 'addTween()'
GetMember

Push    2
	"caurina"		// chain together 'caurina.transitions.Tweener.addTween()'
GetVariable
Push "transitions"
GetMember
Push "Tweener"
GetMember
Push "addTween"
CallMethod			// call 'addTween()'
Pop				// drop return value
}
SetMember			// assign method to class

 

 

Note that both tweens called in there are applied simultaneously, the time it takes to execute the first is added to the delay value of the second one. To remove the additional delay references to XComScrollingTextField.REPEAT_DELAY need to be dropped:

 

first addTween() call:

change
	...
	Push "_alpha" 0 "delay" "XComScrollingTextField"
	GetVariable
	Push "REPEAT_DELAY"
	GetMember
	Push "time"
	...
to
	...
	Push "_alpha" 0 "delay" 0 "time"
	...

or alternatively remove 'delay' parameter altogether:
	...
	Push "_alpha" 0 "time"
	...
	Push "transition" "linear" 4
	InitObject
	...

 

 

second addTween() call:

change
	...
	Push "_alpha" 100 "delay" "XComScrollingTextField"
	GetVariable
	Push "REPEAT_DELAY"
	GetMember
	Push "XComScrollingTextField"
	GetVariable
	Push "FADE_TIME"
	GetMember
	Add2
	Push "time"
	...
to
	...
	Push "_alpha" 100 "delay" "XComScrollingTextField"
	GetVariable
	Push "FADE_TIME"
	GetMember
	Push "time"
	...

 

 

 

And then when the p-code-editor shows things like this:

snip

Then my head only hurts...

The View Hex option of JPEXS' P-code editor is a little bugged, almost every other hex code line is missing a line break, the part you posted should look more like this:

; 96 11 00 00 61 6e 69 6d 61 74 65 43 6f 6d 70 6c 65 74 65 00
Push "animateComplete"
; 8e 08 00 00 00 00 07 29 00 3b 01
DefineFunction2 "" 0 7 false false true false true false false true false {
; 96 11 00 00 5f 61 6c 70 68 61 00 07 00 00 00 00 08 0c 08 0d
Push "_alpha" 0 "delay" "XComScrollingTextField"
; 1c
GetVariable
; 96 02 00 08 0e
Push "REPEAT_DELAY"
; 4e
GetMember
; 96 04 00 08 0b 08 0d
Push "time" "XComScrollingTextField"

.

Does someone think it's feasible to reserve an extra squad slot specifically to SHIVs?

I second this motion :smile: SHIVs have a hard time being included in the squad roster as-is, so allowing some extra soldier slots to be occupied only by SHIVs sounds like a cool way to make players use them more. Plus, they don't show up in the mission loading screen or landing cinematic anyway, so it wouldn't be as immersion-breaking as additional soldiers :wink:

Making those slots available could even be tied to some foundry projects, similar as the OTS upgrades for extra soldiers.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...