Jump to content

[Custom Character] Kerrigan, The Queen of Blades


Seiai

Recommended Posts

post-628848-0-89664400-1433113256_thumb.



 
Steam workshop page:
http://steamcommunity.com/sharedfiles/filedetails/?id=424715104
 
Kerrigan, The Queen of Blades
 
Sarah Kerrigan, the Queen of Blades from Starcraft
 
The Void has ripped her from her world and thrown her into this bizarre new place, hoping to render her helpless and alone.
But the Queen of Blades is never alone. She IS the swarm.
 
Creating zerg units will cost biomass(hunger) and your psychic abilities(max sanity).
Create Overlords to help u control the swarm(restore max sanity).
Create Zerglings to help u fight. U can order them to attack with "R" and to stop with "C"(hotkeys can be changed in the config in the mod menu).
Create drones to help boost your economy!(behaviour adjustable in the config in the mod menu)

Strong unarmed attacks, higher movementspeed, higher hungerrate.
 
Changelog:
V1.22 More Drone AI-Rework and Mod-Configoptions:
drone automatic gather: disable ability of the drones to automaticly gather stuff
drone smart target: disable to reduce cpu stress(if someone has that problem),
but drones may all target the same target
V1.21 Drone AI-Rework
V1.2 Drones join the swarm! Get that economy goin!
V1.1 Overlords have arrived! Now u can actually do that crazy stuff from my previewvideo!



If u like the mod, pls rate it up in the steam workshop!

Pls give me some feedback on balancing, bugs and how u like my mod!
 
Inspirations:
Starcraft 2 by by Blizzard Entertainment.
https://www.youtube.com/watch?v=MVbeoSPqRs4

Starcrafts animations by Carbot Animations:
https://www.youtube.com/watch?v=BBSmo4JW4mk
my favorite episode of Starcrafts:
https://www.youtube.com/watch?v=R_ENGbUSoCw
also, Carbot Animations is trying to create a big mod for SC2 themself:
https://www.youtube.com/watch?v=5xmaPTrQ6CE

Some things i need help with:
  • creep: as far as i know i cant use the spidercreepsystem to create zergcreep, which would be ultracool, so i guess ill have to make it replace the turf on the ground, unless someone has a better idea.

 

Old Versions:

version of the mod before DST was released, in case u have problems and the old version worked:
kerrigan_pre_DST-Version.zip

Link to comment
Share on other sites

@Seiai,

There might be a minimum post or time since registration threshold (I think I recall someone mentioning it before).  Note how your group on your profile is listed as "New User." 

 

 

Not sure what it is, if so though.

 

Out of curiosity, does this link do anything for you?

 

http://forums.kleientertainment.com/index.php?app=forums&module=post&section=post&do=edit_post&f=26&t=52855&p=629443&page=

Link to comment
Share on other sites

thx for the info

well, i guess ill stick with this top post for a while then. i wanted to remove the youtubevideo and just add the channel from carbot animations, i didnt think i would embed it and i dont want it to look like its my video :p

 

Link to comment
Share on other sites

creep: as far as i know i cant use the spidercreepsystem to create zergcreep, which would be ultracool, so i guess ill have to make it replace the turf on the ground, unless someone has a better idea.

 

I've never really looked at how creep works but it looks like it's all over the place.  Klei seems to believe so too, lol:

 

groundcreep.lua

-- This exists solely to make serializing the ground creep from the map sane, as opposed to-- insane special case code that lives god knows where
iam not sure, what would be the best way to make better artwork, i made this mod in gimp with my mouse. i guess i should also make custom animations so i can focus more on the art and less on aligning everthing with existing animations.

 

This is a significantly large undertaking.  There are so many animations, and so many caveats to creating your own.  I made some modifications to the mod tools that might help a bit but I haven't uploaded them yet.  But as someone who personally can barely draw a stick figure, I feel your pain.  I have two friends that work professionally as artists for game companies, and their talent angers me (ex. here and here).

 

I can tell you that the difference in quality/ease between a mouse and a tablet can be extremely high.  My quality mouse (logitech g9) broke and the crappy microsoft mouse I'm using now has the tendency to jump wildly a screen-inch or two when I'm trying to do something pixel perfect.  If I had some disposable income I'd deffo. get a tablet.

 

 

i can by my life not fight out, how to rename the rmb-action string when i hover the mouse over a larva in my inventory(see screenshot on the top). i tried for hours in all kind of different ways.

 

Actions can be a little tricky.  Simply renaming an action isn't too bad though.  When you mouse over anything, the game loops through whatever is under your mouse and executes all of the attached CollectInventoryActions() or CollectSceneActions() methods of your prefab and its components.  There's a couple ways you could approach it, but the safest way would probably be to override the CollectInventoryActions() method on whatever component is adding that action to your prefab.  The string associated with an action is just the str property of that action object. 

 

 

i wanted to do the same with a combatfunction, but i wasnt able to figure out, how i can reference the COMBAT component into the local variable.

 

Assuming inst is the variable that holds the prefab with the combat component, the path to it is just inst.components.combat.

Link to comment
Share on other sites

Yeah, i read some threads about the creep, and it seems its pretty hardcoded.
 

This is a significantly large undertaking.  There are so many animations, and so many caveats to creating your own.  I made some modifications to the mod tools that might help a bit but I haven't uploaded them yet.  But as someone who personally can barely draw a stick figure, I feel your pain.  I have two friends that work professionally as artists for game companies, and their talent angers me (ex. here and here).
 
I can tell you that the difference in quality/ease between a mouse and a tablet can be extremely high.  My quality mouse (logitech g9) broke and the crappy microsoft mouse I'm using now has the tendency to jump wildly a screen-inch or two when I'm trying to do something pixel perfect.  If I had some disposable income I'd deffo. get a tablet.


cool artwork. and yeah, i thought about a tablet, but when i had a look into it, it seems it's hard to find a good one for a decent price. (especially for a sidehobby like this)
 

Actions can be a little tricky.  Simply renaming an action isn't too bad though.  When you mouse over anything, the game loops through whatever is under your mouse and executes all of the attached CollectInventoryActions() or CollectSceneActions() methods of your prefab and its components.  There's a couple ways you could approach it, but the safest way would probably be to override the CollectInventoryActions() method on whatever component is adding that action to your prefab.  The string associated with an action is just the str property of that action object.


i tried to override the str in my CollectInventoryActions(), this is even in the code currently and doesnt work. i tried to overwrite all kinds of parameters, variables and GLOBAL.STRINGS in different places, but nothing worked.
 

Assuming inst is the variable that holds the prefab with the combat component, the path to it is just inst.components.combat.

i know where to find the combat component^^ but i cant override its functions, i tried all kinda of things in the characterscript and the modmain.

i just tried it again with:

local combat = inst.components.combatcombat.GetBattleCryString.fn= function(target) return "For the swarm!" end

in the characterscript, didnt work either.

Link to comment
Share on other sites

combat.GetBattleCryString.fn= function(target) return "For the swarm!" end

 

That code tries to index combat.GetBattleCryString as if it were a table-- which it's not.  Specifically, that code is the equivalent of...

combat.GetBattleCryString["fn"] = function(target) ...

...which has a number of problems.

 

it should read:

function combat:GetBattleCry(target) return "I AM A BANANA." end  [size=1]-- *[/size][size=1]-- * your string may vary[/size]--Alternatively...-- Note that you need to include self in this form because you aren't using colon syntax like above, -- which implies the self parameter.combat.GetBattleString = function(self, target) return "I AM A BANANA!" end

 

 

Actions are a class object that you construct using the by using the Action() function. 

 

actions.lua

Action = Class(function(self, priority, instant, rmb, distance)     self.priority = priority or 0    self.fn = function() return false end    self.strfn = nil    self.testfn = nil    self.instant = instant or false    self.rmb = rmb or nil    self.distance = distance or nilend)

i tried to override the str in my CollectInventoryActions(),

After they are constructed, they are generally stored in the ACTIONS table (GLOBAL.ACTIONS if you're accessing it from modmain.lua).  The game caches them this way because the game needs to constantly collect actions, many times per second.  It would be way too taxing to build actions a bajillion times per second.  When the game collects the actions via Collect_____Actions(), you are just passing a reference to the Action class objects that you want the game to know about.  You don't want to be permanently overwriting that action's string every time it's collected.

 

The cleanest way to do it would be to add a custom action based on the action you want to use. There is a modutil shortcut function to add actions quickly:

 

env.AddAction = function(action)		assert(action.id ~= nil, "Must specify an ID for your custom action! Example: myaction.id = \"MYACTION\"")	initprint("AddAction", action.id)	ACTIONS[action.id] = action	STRINGS.ACTIONS[action.id] = action.strend

 

First create your action using Action(), then add it using AddAction:

local Action = GLOBAL.Actionlocal fancy_new_action = Action()-- You also need to add the id and str properties, as well as the fn method describing what to do when the action is usedfancy_new_action.id = "FINISHTAXES"fancy_new_action.str = "File With IRS"-- Purely illustrativefancy_new_action.fn = function(act)    if act.doer.components.accountant then -- If player is an accountant        act.doer.components.accountant:FileTaxes(act.target)    elseif act.target.components.burnable then -- if player is not an accountant        act.target.components.burnable:Ignite()end

 

 

Link to comment
Share on other sites

That code tries to index combat.GetBattleCryString as if it were a table-- which it's not.

After they are constructed, they are generally stored in the ACTIONS table (GLOBAL.ACTIONS if you're accessing it from modmain.lua).

Ahh, now it makes sense, that it doesnt work for components, ty.

 

Actions are a class object that you construct using the by using the Action() function. 

 

actions.lua

Action = Class(function(self, priority, instant, rmb, distance)     self.priority = priority or 0    self.fn = function() return false end    self.strfn = nil    self.testfn = nil    self.instant = instant or false    self.rmb = rmb or nil    self.distance = distance or nilend)
After they are constructed, they are generally stored in the ACTIONS table (GLOBAL.ACTIONS if you're accessing it from modmain.lua).  The game caches them this way because the game needs to constantly collect actions, many times per second.  It would be way too taxing to build actions a bajillion times per second.  When the game collects the actions via Collect_____Actions(), you are just passing a reference to the Action class objects that you want the game to know about.  You don't want to be permanently overwriting that action's string every time it's collected.

 

The cleanest way to do it would be to add a custom action based on the action you want to use. There is a modutil shortcut function to add actions quickly:

 

env.AddAction = function(action)		assert(action.id ~= nil, "Must specify an ID for your custom action! Example: myaction.id = \"MYACTION\"")	initprint("AddAction", action.id)	ACTIONS[action.id] = action	STRINGS.ACTIONS[action.id] = action.strend
 

First create your action using Action(), then add it using AddAction:

local Action = GLOBAL.Actionlocal fancy_new_action = Action()-- You also need to add the id and str properties, as well as the fn method describing what to do when the action is usedfancy_new_action.id = "FINISHTAXES"fancy_new_action.str = "File With IRS"-- Purely illustrativefancy_new_action.fn = function(act)    if act.doer.components.accountant then -- If player is an accountant        act.doer.components.accountant:FileTaxes(act.target)    elseif act.target.components.burnable then -- if player is not an accountant        act.target.components.burnable:Ignite()end
Well, this is my old code:

i had the component spawnable:

local Spawnable = Class(function(self, inst)

self.inst = inst

end)

local SPAWNLING= Action(1,true,true)

SPAWNLING.id="SpawnLing"

SPAWNLING.str = "Spawn"

SPAWNLING.fn= function(act)

--stuff my action does

return true

end

function Spawnable:CollectInventoryActions(doer, actions, right)

if not self.inst.components.equippable or right then

table.insert(actions, SPAWNLING)

end

end

return Spawnable

and i just regulary added the component to my item/prefab "larva"

 

Now iam trying to do it the way u suggested:

modmain:

local Action = GLOBAL.Action

local SPAWNLING= Action(1,true,true)

SPAWNLING.id="SpawnLing"

SPAWNLING.str = "Spawn"

SPAWNLING.fn= function(act)

--stuff my action does

return true

end

 

AddAction(SPAWNLING)

my Spawnable component :

local Spawnable = Class(function(self, inst)

    self.inst = inst

    

 

end)

 

function Spawnable:CollectInventoryActions(doer, actions, right)

if not self.inst.components.equippable or right then

table.insert(actions, ACTIONS.SPAWNLING)

 

end

end

 

return Spawnable

now i have the problem, that the item doesnt have the action anymore, even though the code compiles(it only offers the standard "examine"). i even tried to add 

AddPrefabPostInit("larva", function(inst) inst:AddComponent("spawnable") end)
which i saw in some other thread, when he used the AddAction function, but it doesnt work either. I tried a few other things, but i cant figure out, how to get the action working now...

i hope the problems i am having stem from the amount of stuff that is hidden in the executable, and not my lack of understanding. this action for the item alone has cost me like 20 hours of codemining already ><

Link to comment
Share on other sites

@Seiai,

 

The vast majority of stuff is done in Lua.  A lot of stuff that isn't done directly in Lua is still exposed to Lua so that you can interact.  Here are all of the C API functions (for DST-- some are't in DS, and some may be slightly different): https://docs.google.com/spreadsheets/d/1oLEjOOJ9-k9PC_JQMw7y5vCNqGDU1niw_XnJCxkBxSU/edit?pli=1#gid=0

 

You won't need most of them. Hell, you won't need almost all of them.

 

 

 

Anyhoo, it's good practice to use the console in game to check out what's going on.  I'd also highly recommend getting the ntools mod. 

 

Here's your problem:

> for k,v in pairs(ACTIONS) do print(k,v) endTURNON table: 0A4BB168NET table: 0A4C79E0SpawnLing table: 0BB28E40STEALMOLEBAIT table: 0A4C4E98ACTIVATE table: 0A4C7E18CHECKTRAP table: 0A4C7710RESETMINE table: 0A4C7DC8TURNOFF table: 0A4BD788PICK table: 0A4C7328...

 

 

Link to comment
Share on other sites

@Seiai,

 

The vast majority of stuff is done in Lua.  A lot of stuff that isn't done directly in Lua is still exposed to Lua so that you can interact.  Here are all of the C API functions (for DST-- some are't in DS, and some may be slightly different): https://docs.google.com/spreadsheets/d/1oLEjOOJ9-k9PC_JQMw7y5vCNqGDU1niw_XnJCxkBxSU/edit?pli=1#gid=0

 

You won't need most of them. Hell, you won't need almost all of them.

 

 

 

Anyhoo, it's good practice to use the console in game to check out what's going on.  I'd also highly recommend getting the ntools mod. 

 

Here's your problem:

> for k,v in pairs(ACTIONS) do print(k,v) endTURNON table: 0A4BB168NET table: 0A4C79E0SpawnLing table: 0BB28E40STEALMOLEBAIT table: 0A4C4E98ACTIVATE table: 0A4C7E18CHECKTRAP table: 0A4C7710RESETMINE table: 0A4C7DC8TURNOFF table: 0A4BD788PICK table: 0A4C7328...
 

That post saved my life, thank u so much!

i have been searching for an API but coudnt find any in the forums, only this "unofficial API"-thing, but i think thats only really the lua-api and stuff.

the time it took me before to find stuff like SetScale...

i mean, theres still hidden stuff in the executable, but i think this api should be linked in the sticky tutorial-threads(i at least didnt see it anywhere), so pple can at least find out what functions exist.(it shouldnt be publicly editable though)

"n tools" are also really cool, didnt come across them before, in all the codingthreads i looked through, should also be in the sticky tutorial-threads imo, saves a lot of printcalls and consoletyping.

as for the ID, the actions-tutorial i used, explained that the ID was used for something else and should be written like that, i never questioned that, this now also explains a few other problems i had...

now i can even leave the action in the component that uses it and just overwrite the global string.

ty again for the help!

Link to comment
Share on other sites

@Corrosive,

would u by any chance know, if i can open the game's fsb soundfiles somehow? i tried to use FMOD. but it doesnt seem to be able to open them, the glommer.fsb just make a wooden "THUMP" noise, and i cant process it with other programmes like audacity either.

Link to comment
Share on other sites

@Seiai,

 

I should have mentioned when I linked you previously-- since that list is for DST functions and may differ from DS, there are ways that you can list DS's UserData(C++) functions via lua.  With any UserData object, when you want to expose functions to the Lua interface, you have to store references to them on the object's metatable.  That means with any UserData object, you can display all available C++ API functions like so:

--using entity as an example, any UserData object works (transform, etc.)print(table.inspect(getmetatable(inst.entity)))
I like to store that somewhere useful, eg

-- there is very rarely anything I do to the output of table.inspect other than print it, -- so might as well include it.table.ins = function(obj)     print(table.inspect(getmetatable(obj)))end
FWIW Components are loaded through require in entityscript.lua, which means that technically they do get cached, but since it gets cached as a factory function, there's not a lot you can do about it.

 

But that doesn't matter all that much, because you can just use AddComponentPostInit() to tweak every component of a given type just after instantiation.

just to have that documented in my thread for future reference, ty again^^

Link to comment
Share on other sites

@Corrosive

btw, a question about "n tools", i have playing around with it a little bit and the "dig" function is a bit confusing to me.

After correcting the ID of my action, i now successfully managed to rename the mouseover of the action with this:

GLOBAL.STRINGS.ACTIONS.SPAWNLING="Spawn"
now i have been trying to "dig" this exact variable with "n tools", but i wasnt able to find it anywhere. do u maybe have any idea where it should be, or why i cant see it? i could not even find the SPAWNLING action in "actions" or "strings" or anywhere...
Link to comment
Share on other sites

@Seiai,

 

The action should be a table located on ACTIONS.SPAWNLING.

 

A tip to make your life easier when using n tools-- what I do when rooting around with it is assign the thing I want to look at to an index on either the global or player tables.  So for example, if I wanted to inspect the equippable component, I would first do Z=GetPlayer().components.equippable in the console, and then in ntools when I want to find it I can just set it to list tables under GLOBAL and hit back once.

 

You can also assign references to variables to the global or player table from your code as well, if you're not sure where they're floating around by the time the game starts up.

Link to comment
Share on other sites

@Corrosive

sry for making u my goto-guy for questions, i just dont wanna open a lot of new threads for these things^^

 

iam considering making custom animations for a creature and iam not sure on how to make the runanimation for 4 directions. For 2 directions, i just add "canrotate" to the statetags in the stategraph and it mirrors the runanimation i specify in 


onenter = function(inst)
            inst.components.locomotor:RunForward()
            inst.AnimState:PushAnimation("walk_loop")
        end,

[code=auto:0]

 

but what do i need to do, to have 2 seperate animations for moving up and down? i guess it has something to do inst.Transform:SetFourFaced(), but i have no idea, how i can specify the animations to use for up and down, or how i have to set up my animation in spriter, so it does that automatically, and i cant find any tutorial or good example of that...

Link to comment
Share on other sites

@Corrosive

sry for making u my goto-guy for questions, i just dont wanna open a lot of new threads for these things^^

 

iam considering making custom animations for a creature and iam not sure on how to make the runanimation for 4 directions. For 2 directions, i just add "canrotate" to the statetags in the stategraph and it mirrors the runanimation i specify in 

onenter = function(inst)

            inst.components.locomotor:RunForward()

            inst.AnimState:PushAnimation("walk_loop")

        end,

[code=auto:0]

 

but what do i need to do, to have 2 seperate animations for moving up and down? i guess it has something to do inst.Transform:SetFourFaced(), but i have no idea, how i can specify the animations to use for up and down, or how i have to set up my animation in spriter, so it does that automatically, and i cant find any tutorial or good example of that...

to make the animation for up/down, you have to create a animation with the name of:

example + _up and example + _down

in your case is walk_loop_up and walk_loop_down, and you will have to rename your old walk_loop animation to walk_loop_side for the game know what to put.

Link to comment
Share on other sites

@mrpoke20xx

ty for the info! and just so i completely understand it:

then i still call it with inst.AnimState:PushAnimation("walk_loop") in the stategraph? and it knows to add the _side, _up and _down because of inst.Transform:SetFourFaced()?

or does the "canrotate" tag do that, and if theres are no _side, _up and _down versions of the animation available, it just falls back to the regular walk_loop and only mirrors it for left and right?

Link to comment
Share on other sites

@mrpoke20xx

ty for the info! and just so i completely understand it:

then i still call it with inst.AnimState:PushAnimation("walk_loop") in the stategraph? and it knows to add the _side, _up and _down because of inst.Transform:SetFourFaced()?

or does the "canrotate" tag do that, and if theres are no _side, _up and _down versions of the animation available, it just falls back to the regular walk_loop and only mirrors it for left and right?

 

yup, is because of inst.Transform:SetFourFaced(), and if it no find _side, _up and _down, it will falls back to the regular walk_loop with mirroring

Link to comment
Share on other sites

@Seiai,

 

Internally, Klei's animation format uses a flag on each compiled animation that specifies which directions(facing) are valid for that animation.

 

The compiler(specifically, buildanimation.py), when parsing scml files, looks for _up _down and _side, and sets the flag accordingly.  Without those suffixes, it flags the animation as valid for all directions.  _side is used to flag both left and right on a single animation, otherwise you'd have to duplicate and flip a left or right animation to get the opposite direction.  You can also specify a separate _left and _right animation, though, in case your sprite is supposed to be asymmetrical (for example, it has a hook on one hand.)

 

def LocalExport( anim_node ):    name = anim_node.attributes["name"].value.encode('ascii')        dirs = (re.search("(.*)_up\Z", name),            re.search("(.*)_down\Z", name),            re.search("(.*)_side\Z", name),            re.search("(.*)_left\Z", name),            re.search("(.*)_right\Z", name))        facingbyte = FACING_RIGHT | FACING_LEFT | FACING_UP | FACING_DOWN        if dirs[0]:        name = dirs[0].group(1)        facingbyte = FACING_UP    elif dirs[1]:        name = dirs[1].group(1)        facingbyte = FACING_DOWN    elif dirs[2]:        name = dirs[2].group(1)        facingbyte = FACING_LEFT | FACING_RIGHT    elif dirs[3]:        name = dirs[3].group(1)        facingbyte = FACING_LEFT    elif dirs[4]:        name = dirs[4].group(1)        facingbyte = FACING_RIGHT

 

The compiler effectively strips off the suffix and compiles the animation with the facing flag set.  This results in compiled animations, all with the same name, but with different facings.

 

Edit: forgot to mention--

 

canrotate effectively allows your character to turn around, which impacts your character's ability to change its facing, but doesn't explicitly have anything to do with what animations get chosen.

Link to comment
Share on other sites

@Seiai,

 

It does.  Those scripts might have been superseded by the RoG scripts, though-- check in DLC0001 for scripts with the same name/path.

yes, i put the print() in both the script from RoG and the regular one. for instance, i tried to output the atlasname of an amulet in the onequip-function in both amulet.lua scripts. and some time ago i tried the same for some functions in both combat.lua scripts... strange...

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

×
  • Create New...