Is it Possible to Add a SIXTH Class to a Side?

Started by Cmd_Smith, February 22, 2015, 06:39:21 PM

Previous topic - Next topic
I'm working on adding the original Battle Droid back onto the CIS side. I dont want to go through all of the hard core.lvl editing, so is it possible just to add a new playable class? I mean,  if theres no other option, i will edit the Assault Droid into the Super Battle Droid and make his rockets more effective... but either way?

So yeah. Is it possible?


You can use the hero class to spawn any AI unit.

You can not have a playable 6th class with the game engine as we currently know it.

It is possible with some trickery to launch a new unit (same as an orbital from a sniper) but this only works in SP.

Quote from: Abraham Lincoln. on November 04, 1971, 12:34:40 PM
Don't believe everything you read on the internet

February 22, 2015, 07:46:30 PM #3 Last Edit: February 22, 2015, 07:49:27 PM by -RepubliqueCmdr-
Not really posting anything constructive (sorry!): but
Quote from: PhobosThere is probably a limit hard-coded that prevents the game from allowing more than 5 units called on for each faction.
I know in AutoIt that when you declare an array (non-dynamic array), you have to give a certain value for allocated indexes in the memory. (Global $Array[5] allocates 5 indexes for the array)

If you try and get the value of an index in the array that exceeds the size of the array, AutoIt throws a fit about it and can cause a crash.--
My point is, if the spawnable units are set into some sort of array (probably a two dimensional array to contain the teams like
Code (lua) Select
SpawnUnits[1,5] = EntityClass('all_inf_soldier'); --[team #, unit selection]), then trying to give an array index a value when it doesn't exist in the memory would likely cause issues.

I don't know if that's how battlefront handles it, but it seems reasonable to me. (If we had the source we could probably find out..)

SO is BF2 hard-coded the same way? Is it unable to have 7 classes, or 5? I'm aware you can have less than 5 in SWBF1. Either way, it wont matter XD I'll just modify the other ones.

Quote from: Cmd_Smith on February 23, 2015, 07:11:34 AM
SO is BF2 hard-coded the same way? Is it unable to have 7 classes, or 5? I'm aware you can have less than 5 in SWBF1. Either way, it wont matter XD I'll just modify the other ones.
Well, in truth, we don't know if it is hard-coded in either game. The class limit for BF2 is 10 per team (or 9+1 hero per team). And it is possible to have 5 or less units per team in both games. Though there is an SP-only workaround to add extra units.

Quote from: Commander Awesome on February 23, 2015, 10:06:26 AM
Well, in truth, we don't know if it is hard-coded in either game. The class limit for BF2 is 10 per team (or 9+1 hero per team). And it is possible to have 5 or less units per team in both games. Though there is an SP-only workaround to add extra units.
You could say we don't have 100% certainty, but we are fairly certain, because of reference in BF2's spawn script, that it is hard-coded under "pcspawnselect.h" or something like it, with the max units defined in the script.
The BOBclan:  A Rich History


Quote from: Unit 33 on November 29, 2014, 03:44:44 AM
'Please, tell me more about the logistics of the design of laser swords being wielded by space wizards' - Some guy on the internet.

Quote from: Dark_Phantom on February 24, 2015, 05:50:56 PM
You could say we don't have 100% certainty, but we are fairly certain, because of reference in BF2's spawn script, that it is hard-coded under "pcspawnselect.h" or something like it, with the max units defined in the script.

Indeed, everything has its limits. 

IPv4 address space 4294967296 (2^32) addresses
IPv6 address space 2^128

Playable Spawn slots on SWBF1:  5

Quote from: Abraham Lincoln. on November 04, 1971, 12:34:40 PM
Don't believe everything you read on the internet

Quote from: Led on February 24, 2015, 06:03:08 PM
Indeed, everything has its limits. 

IPv4 address space 4294967296 (2^32) addresses
IPv6 address space 2^128

Playable Spawn slots on SWBF1:  5



I had a nice laugh with this :)  We are running out of IPv4 addresses!
The BOBclan:  A Rich History


Quote from: Unit 33 on November 29, 2014, 03:44:44 AM
'Please, tell me more about the logistics of the design of laser swords being wielded by space wizards' - Some guy on the internet.

February 26, 2015, 10:29:47 PM #9 Last Edit: February 26, 2015, 10:39:35 PM by Phobos
On line 29 of ifs_pc_SpawnSelect.lua you can increase the local numSlots value to a higher number, 5 will add 6th unit button, 6 will add a 7th, etc. The problem is that adding 6 or more units to the mission LUA for a player team will cause an instant crash if you try to play on that team. However, you can add 6+ units to local sides without crash, and even one of the primary sides, as long as you don't switch to that team on the spawn menu. Battlefront crashes because the limit is hard-coded in the game, in the file pcSpawnDisplay.h. Fred cannot share this file or other EXE source scripts, but he was generous enough to share the LUA.

Quote from: Phobos on February 21, 2013, 07:11:03 PM
it's interesting to note that in the bf2 spawnselect lua this is mentioned

local MAX_CLASS_SLOTS = 10 -- must match MAX_CLASS_SLOTS in pcSpawnDisplay.h

--make sure there's at least 7 slots, but not more than MAX_CLASS_SLOTS, depending on how many classes are available in the map
local numSlots = math.min( math.max(7, GetTeamClassCount(1), GetTeamClassCount(2)), MAX_CLASS_SLOTS )


The bf1 lua does not mention any reference to pcSpawnDisplay.h but I suspect it is most likely also used in bf1 and has a maximum hard coded value of 5 units per team. If this was somehow increased to 6, it "might" prevent the game from crashing when 6 units are called on through the LUA. This is just speculation however.

ifs_pc_SpawnSelect.lua

--This is the PC version of the charselect, which includes elements of the spawndisplay
-- all the if mode stuff has been removed, as there is no splitscreen for PC

-- Helper function. Builds the chunks for this screen programatically
-- (i.e. based on screensize). It makes and shoves things into the
-- 'this.Info' block, which is a container aligned to the right-middle
-- of the screen. Thus, within its space, x=0 is the right edge,
-- x=-100 is to its left. y=0 is the middle of the screen, y=-100 is
-- above that, y=100 is below.

function ifs_pc_SpawnSelect_fnBuildScreen(this, mode)

-- Make a container that's aligned to the left-top of the screen
-- to shove our stuff into
this.Info = NewIFContainer {
ScreenRelativeX = 0.0,
ScreenRelativeY = 0.0,
inert = 1, -- delete from Lua memory once pushed to C
}

this.BotInfo = NewIFContainer {
ScreenRelativeX = 1.0,
ScreenRelativeY = 1.0,
inert = 1, -- delete from Lua memory once pushed to C
}

local w,h = ScriptCB_GetSafeScreenInfo() -- of the usable screen
local numSlots = 4 -- 0 to 5 (6 total) --REDUCED BY 1
local boxw, boxh, texth
-- Scale a box based on screensize
boxw = w * 0.35
boxh = h * 0.05--could be too small
local textheight = boxh * 1.6
local sideh = h * 0.15
local sidew =   w * 0.1   

local okcancelw = w * 0.2
local okcancelh = h * 0.12


local fontsize = "gamefont_tiny"

local barw = boxw * 1.3

local SideXOffset = w * .1
local SideYOffest = h * .125

local SlotUnitNameOffsetX = w * .05 --will need the icon offset eventually
local SlotYOffset = h * .015 + sideh --will need to add the SideIcons offset eventually

SlotYOffset = sideh/2
local SlotTextOffsetX = SlotUnitNameOffsetX + 20

local popupWidth  = w * .3
local popupHeight = h * .15
local leftsideRot = 35
--Make two buttons for the two sides, (a frame and an bitmap for each)
--These are the frames

Icon0PosX = w/2 - sidew/2
Icon1PosX = w/2 + sidew/2

this.Info.SideIcon0 = NewBorderRect
{
ZPos = 190, -- behind most
x = w/2,
y = SideYOffest,
width = sidew*2,
height = sideh,
alpha = 0, -- invisible hotspot, here we come.
}
this.Info.SideIcon1 = NewBorderRect
{
ZPos = 190, -- behind most
x = w/2,
y = SideYOffest,
width = sidew * 2,
height = sideh,
alpha = 0,
}
--The two bitmaps
-- this.Info.SideImage0 = NewIFImage
-- {
-- ZPos = 180,
-- x = Icon0PosX,
-- y = SideYOffest, -- inertUVs = 1,
-- alpha = 255,
-- localpos_l = -sidew/4, localpos_t = -sideh/4,
-- localpos_r =  sidew/4, localpos_b =  sideh/4,
-- --texture = "CharSelectImp_BG",
-- ColorR = 0, ColorG = 0, ColorB = 0, -- black
-- }

-- this.Info.SideImage1 = NewIFImage
-- {
-- ZPos = 180,
-- x = Icon1PosX,
-- y = SideYOffest, -- inertUVs = 1,
-- alpha = 255,
-- localpos_l = -sidew/4, localpos_t = -sideh/4,
-- localpos_r =  sidew/4, localpos_b =  sideh/4,
-- --texture = "CharSelectImp_BG",
-- ColorR = 0, ColorG = 0, ColorB = 0, -- black
-- }

this.Info.SideModel0 = NewIFModel {
x = Icon0PosX, y = SideYOffest,
scale = LargeScale,
OmegaY = 0.2,
lighting = 1,
ColorR = 76, ColorG = 180, ColorB = 255,
}
this.Info.SideModel1 = NewIFModel {
x = Icon1PosX, y = SideYOffest,
scale = LargeScale,
OmegaY = 0.2,
lighting = 1,
ColorR = 76, ColorG = 180, ColorB = 255,
}





--Make two buttons for the Accept & Cancel button
--And the text that goes in them
this.Info.Ok = NewBorderRect
{
ZPos = 190, -- behind most
--x = w - okcancelw + 80,
x= w/2,
y = h - okcancelh + 50,
width = okcancelw,
height = okcancelh,
alpha = 128,
rotX = 45,
}
this.Info.TextOk = NewIFText --
{
--x = w - 1.5 * okcancelw + 80,
--y = h - 1.5 * okcancelh + 50,
x = w/2 - okcancelw/2,
y = h - 1.5 * okcancelh + 50,
font = fontsize,
halign = "hcenter",
valign = "vcenter",

--halign = "left",
--valign = "top",

textw = okcancelw , -- usable area for text
texth = okcancelh  ,
font = fontsize,
string = "ifs.SpawnDisplay.Spawn",
ColorR = 255, ColorG = 255, ColorB = 255, -- white
flashy = 0,

}

-- this.Info.Cancel = NewBorderRect
-- {
-- ZPos = 190, -- behind most
-- x = 0, -- + w*.02 + ,
-- y = h,  -- okcancelh,
-- width = okcancelw,
-- height= okcancelh,
-- alpha = 128,
-- }
--
-- this.Info.TextCancel = NewIFText --the Unit's name/soldiertype/title
-- {
-- x = 0, -- center-x position
-- y = h , -- just touching box below (my height = 32, but is centered)
-- width = barw * 10,
-- font = fontsize,
-- halign = "left",
-- valign = "top",
-- textw = okcancelw - 32, -- usable area for text
-- texth = okcancelh - 32 ,
-- font = fontsize,
-- string = "Cancel",
-- ColorR = 255, ColorG = 255, ColorB = 255, -- white
-- }

--Make a box for the mission briefing screen above the map -- Low priority
--Make several containers for each of the class slots (probably safe with seven)
-- each slot needs a frame, a unit title and unit text


--a class slot should look like:
-- ---------------------------------------------|
-- | --Icon | --SoldierType |
-- | |   -- Eq List |
--      ----------------------------------------------
local i
for i = 0,numSlots do

local tag = format("SlotUnitName%d",i)

-- this.Info[tag] = NewIFText --the Unit's name/soldiertype/title
-- {
--- x = SlotTextOffsetX, --SlotUnitNameOffsetX , -- center-x position
--- y = SlotYOffset + i * ( boxh + textheight ), -- just touching box below (my height = 32, but is centered)
-- width = barw * 10,
---- font = fontsize,
-- halign = "left",
-- valign = "top",
-- -- textw = barw , -- usable area for text
-- texth = 32,  --boxh ,
-- font = fontsize,
-- string = "UnitTitle",
-- ColorR = 255, ColorG = 255, ColorB = 255, -- white
-- --flashy = 0,
-- rotY = 20,
-- bgleft = "headerbuttonleft",
-- bgmid = "headerbuttonmid",
-- bgright = "headerbuttonright",
--
-- textw = boxw, -- usable area for text
-- }


tag = format("SlotWindow%d",i)
-- -- this.Info[tag] = NewBorderRect
-- -- {
-- -- ZPos = 190, -- behind most
-- -- x = SlotUnitNameOffsetX +  65,
-- -- y = SlotYOffset + i * ( boxh + textheight ) + boxh,
-- -- width = boxw,
-- -- height = textheight + boxh,
-- -- alpha = 128,
-- -- }

this.Info[tag] = NewButtonWindow
{
ZPos = 200,
x=SlotUnitNameOffsetX +  SlotUnitNameOffsetX * 2.5,
y = SlotYOffset + i * ( boxh + textheight +  ScriptCB_GetFontHeight(fontsize)+10 ) + boxh ,
--ScreenRelativeX = 0.0, -- center
--ScreenRelativeY = 0.0,
width = boxw,
height = textheight + boxh,
titleText = "ifs.profile.list",
rotY = leftsideRot,
font = fontsize
}

this.Info[tag].bHotspot = 1
this.Info[tag].fHotspotW = boxw
this.Info[tag].fHotspotH = textheight + boxh


this.Info[tag].InfoText = NewIFText  --the equipment/weapon text
    { 
--x = 0, --SlotTextOffsetX ,
--y = 0, --SlotYOffset + i * ( boxh + textheight ) + ScriptCB_GetFontHeight(fontsize) + 30  ,


width = barw * 10,

halign = "hcenter",
valign = "vcenter",
textw = boxw, -- usable area for text
texth = textheight,
font = fontsize,
string = "InfoText",
ColorR = 255, ColorG = 255, ColorB = 255, -- white
--rotY = 20,
flashy = 0,
--x = -boxw,
--y = -textheight,
}

end
-- Now for a popup textbox (position is unimportant, gets set on the fly)
-- this.Info.PopupText = NewIFText  --the equipment/weapon text
--
-- x = w - (popupWidth - 16),
-- y = h - (popupHeight - 16),
-- halign = "left", --could be changed by code
-- valign = "top",
-- textw = popupWidth, -- usable area for text
-- texth = popupHeight,
-- font = fontsize,
-- string = "InfoText",
-- ColorR = 255, ColorG = 255, ColorB = 255, -- white
-- flashy = 0,
---
-- }
-- this.Info.PopupBorder = NewBorderRect
-- {
-- ZPos = 190, -- behind most
-- x = w - (popupWidth/2),
-- y = h - (popupHeight/2),
-- width = popupWidth,
-- height = popupHeight,
-- alpha = 128,
-- }

this.Info.PopupWindow = NewButtonWindow
{
ZPos = 200,
x = w - (popupWidth/2),
y = h - (popupHeight/2),
--ScreenRelativeX = 0.0, -- center
--ScreenRelativeY = 0.0,
width = popupWidth,
height = popupHeight,
titleText = "",
rotY = -20,
font = fontsize
}

this.Info.PopupWindow.Text = NewIFText  --Spawnpoint text

x = -(popupWidth - 16 )/2,
y = - (popupHeight - 16)/2,
halign = "hcenter", --could be changed by code
valign = "vcenter",
textw = popupWidth - 16, -- usable area for text
texth = popupHeight - 16,
font = fontsize,
string = "InfoText",
ColorR = 255, ColorG = 255, ColorB = 255, -- white
flashy = 0,
}



this.Info.ObjectiveWindow = NewButtonWindow
{
ZPos = 1,
x = w - (popupWidth/2),
y = (popupHeight/2) + h*.05,
--ScreenRelativeX = 0.0, -- center
--ScreenRelativeY = 0.0,
width = popupWidth,
height = popupHeight,
titleText = "ObjectivesGoHere",
rotY = -20,
font = fontsize

}

this.Info.ObjectiveWindow.Text = NewIFText  --objective text

x = -(popupWidth - 16 )/2,
y = - (popupHeight - 16)/2,
halign = "top", --could be changed by code
valign = "vcenter",
textw = popupWidth - 16, -- usable area for text
texth = popupHeight - 16,
font = fontsize,
string = "InfoText",
ColorR = 255, ColorG = 255, ColorB = 255, -- white
flashy = 0,
}

--This is the selected icon that shows up by the class slot
this.Info.SelectedImage = NewIFImage
{
ZPos = 180,
x = 0,
y = 0, -- inertUVs = 1,
alpha = 255,
localpos_l = -sidew/4, localpos_t = -sideh/4,
localpos_r =  sidew/4, localpos_b =  sideh/4,
--texture = "CharSelectImp_BG",
ColorR = 0, ColorG = 0, ColorB = 0, -- black
}

end

function ifs_pc_spawnselect_animateicons(which)
local this = ifs_pc_SpawnSelect

local w,h = ScriptCB_GetSafeScreenInfo()
local SideYOffest = h * .13
local Icon0PosX = w/2 - w*0.05
local Icon1PosX = w/2 + w*0.05

local resScale = w / 800

if(which < 0.5) then
AnimationMgr_AddAnimation(this.Info.SideModel0,{ fTotalTime = 0.25,fStartAlpha = 0.35, fEndAlpha = 1,
fStartX = Icon1PosX,fEndX = Icon0PosX,
fStartY = SideYOffest,fEndY = SideYOffest,
fStartW = 0.25*resScale,fStartH = 0.25*resScale,fEndW   = 0.5*resScale,fEndH   = 0.5*resScale,})
AnimationMgr_AddAnimation(this.Info.SideModel1,{ fTotalTime = 0.25,fStartAlpha = 1, fEndAlpha = 0.35,
fStartX = Icon0PosX,fEndX = Icon1PosX,
fStartY = SideYOffest,fEndY = SideYOffest,
fStartW = 0.5*resScale,fStartH = 0.5*resScale,fEndW   = 0.25*resScale,fEndH   = 0.25*resScale,})
else
AnimationMgr_AddAnimation(this.Info.SideModel0,{ fTotalTime = 0.25,fStartAlpha = 1, fEndAlpha = 0.35,
fStartX = Icon0PosX,fEndX = Icon1PosX,
fStartY = SideYOffest,fEndY = SideYOffest,
fStartW = 0.5*resScale,fStartH = 0.5*resScale,fEndW   = 0.25*resScale,fEndH   = 0.25*resScale,})
AnimationMgr_AddAnimation(this.Info.SideModel1,{ fTotalTime = 0.25,fStartAlpha = 0.35, fEndAlpha = 1,
fStartX = Icon1PosX,fEndX = Icon0PosX,
fStartY = SideYOffest,fEndY = SideYOffest,
fStartW = 0.25*resScale,fStartH = 0.25*resScale,fEndW   = 0.5*resScale,fEndH   = 0.5*resScale,})
end

-- make them spin fast for a bit
ScriptCB_IFModel_SetOmegaY(this.Info.SideModel0.cpointer,-20)
ScriptCB_IFModel_SetOmegaY(this.Info.SideModel1.cpointer,-20)
this.IconModelFastMode = 1
end

ifs_pc_SpawnSelect = NewIFShellScreen
{
nologo = 1,
bNohelptext_accept = 1, -- we have our own
bNohelptext_backPC = 1,



-- Actual contents are created in ifs_charselect_fnBuildScreen
-- Note: for now, the exe is handling all the inputs/events, so this
-- screen has no Enter/Exit/Update/Input handlers. It does have an
-- Input_Back handler to override the base class's default functionality
-- (go to previous screen)
Input_Back = function(this)
end,
Input_GeneralLeft = function(this,bFromAI)
end,
Input_GeneralRight = function(this,bFromAI)
end,
Input_GeneralUp = function(this,bFromAI)
end,
Input_GeneralDown = function(this,bFromAI)
end,

Update = function(this,fDt)
-- Call default base class's update function (make button bounce)
gIFShellScreenTemplate_fnUpdate(this,fDt)
-- if the models are done animating, slow down the rotations
if(this.IconModelFastMode and not this.Info.SideModel0.bAnimActive) then
ScriptCB_IFModel_SetOmegaY(this.Info.SideModel0.cpointer,-0.3)
ScriptCB_IFModel_SetOmegaY(this.Info.SideModel1.cpointer,-0.3)
this.IconModelFastMode = nil
end
end,

}
ifs_pc_SpawnSelect_fnBuildScreen(ifs_pc_SpawnSelect, 0)
AddIFScreen(ifs_pc_SpawnSelect,"ifs_pc_SpawnSelect")
ifs_pc_SpawnSelect_fnBuildScreen = nil

February 26, 2015, 11:06:03 PM #10 Last Edit: February 26, 2015, 11:14:03 PM by -RepubliqueCmdr-
Say..
local SlotUnitNameOffsetX = w * .05 --will need the icon offset eventually
I noticed troop icons not used (that I have found) by the game in side assets (htrooper_icon tga stuff), I wonder if those icons were an intended feature in the spawn select menu and never got added in..

Would have been kinda neat to have little icons in the Spawn menu Troop/Unit selectors.. I wonder if that could be activated, or if whomever did the scripting never got to that..
--
Lol, reading a little further makes obvious the answer to my question. Cool, But now I feel a bit sheepish.
--
FOR THE LOVE OF ALL GOOD THINGS, we must uncomment the this.Info.SideImage0 = NewIFImage containers to see if they work ingame..
--
It looks the the functionality might be there, with the positioning of the icons and all (of course you might accommodate the width of the icons for the actual spawn button width), just the actual image definition parts are commented out..