Sign in to follow this  
Purswader

How to add a new key function

Recommended Posts

Purswader    7

Basicly i want my character to change his animations and perks etc, by pressing a key. But i can't get this to work, cause i keep crashing or basicly nothing happens. Here is my code modmain.lua:

[codesyntax]

local require = GLOBAL.require
local Ingredient = GLOBAL.Ingredient
local RECIPETABS = GLOBAL.RECIPETABS
local STRINGS = GLOBAL.STRINGS
local ACTIONS = GLOBAL.ACTIONS
local Action = GLOBAL.Action
local TECH = GLOBAL.TECH
local WorldSanityMonsterSpawner = require("components.WorldSanityMonsterSpawner")
local TheInput = require("input")

STRINGS.NAMES.GIR = "GIR"
STRINGS.CHARACTER_TITLES.gir = "Information Retrieval Unit"
STRINGS.CHARACTER_NAMES.gir = "GIR"
STRINGS.CHARACTER_DESCRIPTIONS.gir = "*Lovely little robot"--\n*Dies from water"
STRINGS.CHARACTER_QUOTES.GIR = "\"I love this show! \""
STRINGS.CHARACTERS.GIR = require "speech_gir"
STRINGS.CHARACTERS.GENERIC.DESCRIBE.GIR = "Lovely little robot"
STRINGS.CHARACTERS.GIR.DESCRIBE.GIR = {"Hello.", "Hi."}
STRINGS.CHARACTERS.WICKERBOTTOM.DESCRIBE.GIR = ("I like to examine that unit.")
STRINGS.CHARACTERS.WAXWELL.DESCRIBE.GIR = ("How did you get here?")
STRINGS.CHARACTERS.WOODIE.DESCRIBE.GIR = ("It looks funny, Lucy.")
STRINGS.CHARACTERS.WOLFGANG.DESCRIBE.GIR = ("It's small. I could try eat it")
STRINGS.CHARACTERS.WENDY.DESCRIBE.GIR = ("It smells like meat.")
STRINGS.CHARACTERS.WX78.DESCRIBE.GIR = ("DAMAGED STANDARD-ISSUE INFORMATION RETRIVAL UNIT.")


STRINGS.CHARACTERS.GIR.ANNOUNCE_NOSANITY = "Yes, my master!"    

PrefabFiles = {
    "gir",
}

ComponentsFiles = {
    "WorldSanityMonsterSpawner",
}

Assets = {
    Asset( "IMAGE", "images/saveslot_portraits/gir.tex"),
    Asset( "ATLAS", "images/saveslot_portraits/gir.xml"),
    
    Asset( "IMAGE", "images/selectscreen_portraits/gir.tex" ),
    Asset( "ATLAS", "images/selectscreen_portraits/gir.xml" ),

    Asset( "IMAGE", "images/selectscreen_portraits/gir_silho.tex" ),
    Asset( "ATLAS", "images/selectscreen_portraits/gir_silho.xml" ),

    Asset( "IMAGE", "bigportraits/gir.tex" ),
    Asset( "ATLAS", "bigportraits/gir.xml" ),

    Asset( "IMAGE", "minimap/gir.tex" ),
    Asset( "ATLAS", "minimap/gir.xml" ),
    
    Asset("SOUNDPACKAGE", "sound/gir.fev"),
    Asset("SOUND", "sound/gir_bank01.fsb"),
        
    Asset( "IMAGE", "images/avatars/avatar_gir.tex" ),
    Asset( "ATLAS", "images/avatars/avatar_gir.xml" ),
    
    Asset( "IMAGE", "images/avatars/avatar_ghost_gir.tex" ),
    Asset( "ATLAS", "images/avatars/avatar_ghost_gir.xml" ),
    }

GetPlayer = GLOBAL.GetPlayer
AddMinimapAtlas("minimap/gir.xml")



RemapSoundEvent( "dontstarve/characters/gir/death_voice", "gir/characters/gir/death_voice" )
RemapSoundEvent( "dontstarve/characters/gir/hurt", "gir/characters/gir/hurt" )
RemapSoundEvent( "dontstarve/characters/gir/talk_LP", "gir/characters/gir/talk_LP" )


GLOBAL.STRINGS.CHARACTERS.gir = GLOBAL.require("speech_gir")

AddModCharacter("gir")
table.insert(GLOBAL.CHARACTER_GENDERS.MALE, "gir")

for k, v in pairs(CHARACTERLIST) do
    if v.prefab ~= "wx78" then
        AddPrefabPostInit(v, ModCharacterInit)
    end
end


for k,v  in pairs(GLOBAL.MODCHARACTERLIST) do
    AddPrefabPostInit(v, ModCharacterInit)
end

GIRKeyHandler = Class(function(self)   
    self.handler = TheInput:AddKeyHandler(function(key, down) self:OnRawKey(key, down) end )
end)

function GIRKeyHandler:OnRawKey(key, down)
    if (key == KEY_T and not down) then
        print("test")
    end
end

theGIRKeyHandler = GIRKeyHandler()

[/codesyntax]

with this version i get the error log.txt:

[codesyntax]

[string "scripts/input.lua"]:124: attempt to index field 'onkey' (a nil value)
LUA ERROR stack traceback:
        scripts/input.lua(124,1) in function 'AddKeyHandler'
        ../mods/gir together/modmain.lua(90,1) in function '_ctor'
        scripts/class.lua(181,1) in function 'GIRKeyHandler'
        ../mods/gir together/modmain.lua(99,1) in main chunk
        =[C] in function 'xpcall'
        scripts/util.lua(455,1) in function 'RunInEnvironment'
        scripts/mods.lua(309,1) in function 'InitializeModMain'
        scripts/mods.lua(290,1) in function 'LoadMods'
        scripts/main.lua(245,1) in function 'ModSafeStartup'
        scripts/main.lua(293,1)
        =[C] in function 'SetPersistentString'
        scripts/mainfunctions.lua(24,1) in function 'SavePersistentString'
        scripts/modindex.lua(76,1)
        =[C] in function 'GetPersistentString'
        scripts/modindex.lua(63,1) in function 'BeginStartupSequence'
        scripts/main.lua(292,1) in function 'callback'
        scripts/modindex.lua(342,1)
        =[C] in function 'GetPersistentString'
        scripts/modindex.lua(322,1) in function 'Load'
        scripts/main.lua(291,1) in main chunk
Error error! We tried displaying an error but TheFrontEnd isn't ready yet...  

[/codesyntax]

 

Any help would be appreciated.

Edited by Purswader

Share this post


Link to post
Share on other sites
Kzisor    1060

You are trying to add a local variable which to GIRKeyHandler, yet you are trying to call a global variable from within your key press functionality.

 

Try something along these lines:

GIRKeyHandler.OnRawKey = function(key, down)if (key == KEY_T and not down) thenprint("test")endend

For more information check out: http://www.lua.org/pil/6.2.html

Edited by Kzisor

Share this post


Link to post
Share on other sites
Kzisor    1060

@Kzisor, thank you for your help, but i already deleted the local environment, i updated my crash and code just a few minutes ago

 

Here is the working code:

 

local TheInput = GLOBAL.TheInputlocal KEY_T = GLOBAL.KEY_T GIRKeyHandler = Class(function(self)       self.handler = TheInput:AddKeyHandler(function(key, down) self:OnRawKey(key, down) end )end)     function GIRKeyHandler:OnRawKey(key, down)     if (key == KEY_T and not down) then         print("test")     endendtheGIRKeyHandler = GIRKeyHandler()

Share this post


Link to post
Share on other sites
Purswader    7

@Kzisor, thank you again, but i got that going just a few minutes before and was just about to change my question again ^^ just thinking about how to explain it right now

Edited by Purswader

Share this post


Link to post
Share on other sites
Kzisor    1060

@Purswader, should be as simple as the following:

 

GIRKeyHandler = Class(function(self)   
    self.handler = TheInput:AddKeyHandler(function(key, down) self:OnRawKey(key, down) end )
end)
 
    function GIRKeyHandler:OnRawKey(key, down)
     if (key == KEY_T and not down) then
         print("test")
     end
end

theGIRKeyHandler = GIRKeyHandler()

 

Inside script/prefabs folder TheInput and Key_T is already global.

 

EDIT:

However, it's not going to be that simple as I just tested that. I think it would probably work if you added it in the modmain.lua and initialize it as a component and simple add it as a component to GIR.

Edited by Kzisor

Share this post


Link to post
Share on other sites
Kzisor    1060

@Purswader, okay so after some testing I figured out how to properly implement this as a component. Now you will need to adjust it the way you want but in order to do anything with it with your character all you have to do is inst:AddComponent("keyhandler") in your character file.

 

Add a keyhandler.lua file under the scripts/components folder and put this code in it.

 

local KeyHandler = Class(function(self, inst)
self.inst = inst
self.handler = TheInput:AddKeyHandler(function(key, down) self:OnRawKey(key, down) end )
end)
 
function KeyHandler:OnRawKey(key, down)
  if (key == KEY_T and not down) then
      print("test")
  end
end
 

return KeyHandler

 

 

This worked whenever I tested it if you have troubled let me know and I'll upload a working concept mod.

Share this post


Link to post
Share on other sites
Purswader    7

@Kzisor, i have one minor problem, if the game is paused or you try to chat or use the console, the function will also be applied. Of course it should only be applied when active playing. I will look how to do this, but maybe you work faster. ^^

 

Edit:

and it wont work, if you are not the host.

 

Edit:

if the host presses T things changing on my character. Thats somehow funny.

Edited by Purswader

Share this post


Link to post
Share on other sites
Kzisor    1060

@Kzisor, i have one minor problem, if the game is paused or you try to chat or use the console, the function will also be applied. Of course it should only be applied when active playing. I will look how to do this, but maybe you work faster. ^^

 

Edit:

and it wont work, if you are not the host.

 

Edit:

if the host presses T things changing on my character. Thats somehow funny.

 

I'm still figuring out how to get it to work on the client side. Once I figure that out, I might be able to figure out how to only make it work by said player.

 

Edit:

Forgot to mention that if you only want it to work when the game is running you need to add this if statement.

 

if IsPaused() then return end

 

Alternatively you could add 'not IsPaused()' to the already provided if statement.

Edited by Kzisor

Share this post


Link to post
Share on other sites
Kzisor    1060

@Kzisor, I'm glad to hear that you are working on it. I can't get this wo work, but i'm still trying.

 

Here is the updated code which makes it work only when the game is actively running.

 

local KeyHandler = Class(function(self, inst)
self.inst = inst
self.handler = TheInput:AddKeyHandler(function(key, down) self:OnRawKey(key, down) end )
end)
 
function KeyHandler:OnRawKey(key, down)
  if (key == KEY_T and not down) and not IsPaused() then
      print("test")
  end
end
 
return KeyHandler

Share this post


Link to post
Share on other sites
Kzisor    1060

@Kzisor, i was talking about that client thing ;), but thank you ^^

 

I got that working as well, although I had to change the code a little.

 

KeyHandler.lua

local KeyHandler = Class(function(self, inst)

self.inst = inst
self.handler = TheInput:AddKeyHandler(function(key, down) self:OnRawKey(key, down) end )
end)
 
function KeyHandler:OnRawKey(key, down)
local player = ThePlayer
  if (key and not down) and not IsPaused() then
      player:PushEvent("keypressed", {player = player, key = key})
  end
end
 
return KeyHandler
 
modmain.lua/character prefab.lua
local function OnKeyPressed(inst, data)
if data.player == GLOBAL.ThePlayer then
print(tostring(data.key))
end
end
 
Wilson = function(self)
self:AddComponent("keyhandler")
 
self:ListenForEvent("keypressed", OnKeyPressed)
 
return self
end
 
AddPrefabPostInit("wilson", Wilson)
 
This will do exactly what you are wanting to do.
Edited by Kzisor

Share this post


Link to post
Share on other sites
Purswader    7

@Kzisor, first of all, you are awesome. I will try this in a few minutes. Can you please explain where i have to define which key must be pressed? i'm not able to figuere that out on my first look at your code.

Share this post


Link to post
Share on other sites
Kzisor    1060

@Kzisor, first of all, you are awesome. I will try this in a few minutes. Can you please explain where i have to define which key must be pressed? i'm not able to figuere that out on my first look at your code.

 

You define which key you specifically want to listen for by altering this function.

 

local function OnKeyPressed(inst, data)

if data.player == GLOBAL.ThePlayer then
   if data.key == GLOBAL.KEY_T then
      print("KEY_T has been pressed.")
   end
end
end

Share this post


Link to post
Share on other sites
Purswader    7

@Kzisor, k i have some difficulties implementing your code, where should i put the secound one? If i try modmain the character.lua doesn't no the function OnKeyPressed(inst, data) and if i put it all in the character file it doesn't know the GLOBAL variable.

 

Edit:
wait i think i got it.

 

Edit:

It does not work the way i did it. On hosting it worked fine, but on client side not. I show you what i did:

 

keyhandler.lua (in components)

local KeyHandler = Class(function(self, inst)self.inst = instself.handler = TheInput:AddKeyHandler(function(key, down) self:OnRawKey(key, down) end )end)function KeyHandler:OnRawKey(key, down)local player=ThePlayerif (key and not down) and not IsPaused() thenplayer:PushEvent("keypressed",{player = player,key = key})endendreturn KeyHandler

 

and in the gir.lua (in prefabs)

local function OnKeyPressed(inst, data)if data.player == ThePlayer thenif data.key == KEY_T thenif (inst.strength=="normal" or inst.strength=="mighty") thenlocal damage_mult = 0.9local health_max = 150local hunger_rate = 1.7local scale = 0.9local speed = 1.1inst.AnimState:SetBuild("gir_dog")inst.strength="dog"inst.Transform:SetScale(scale,scale,scale)inst.components.hunger:SetRate(hunger_rate*TUNING.WILSON_HUNGER_RATE)inst.components.combat.damagemultiplier = damage_multinst.components.locomotor.walkspeed = (TUNING.WILSON_WALK_SPEED * speed)inst.components.locomotor.runspeed = (TUNING.WILSON_RUN_SPEED * speed)inst.components.sanity.dapperness = 0local health_percent = inst.components.health:GetPercent()inst.components.health:SetMaxHealth(health_max)inst.components.health:SetPercent(health_percent, true)elseif (inst.strength=="dog" and inst.components.sanity.current < 85) theninst.strength="mighty"elseif (inst.strength=="dog" and inst.components.sanity.current > 85) theninst.strength="normal"endendendend

 

and he has inst:ListenForEvent("keypressed", OnKeyPressed) ofc

Edited by Purswader

Share this post


Link to post
Share on other sites
Kzisor    1060

@Purswader, the problem you are faced with has to do with networking. In order for your client to be able to change things on the server, you must sent a request to the server to have them changed. Instead of setting the components on the client side you must set the replica on the client side.

 

Try the following:

local function OnKeyPressed(inst, data)if data.player == ThePlayer thenif data.key == KEY_T thenif (inst.strength=="normal" or inst.strength=="mighty") thenlocal damage_mult = 0.9local health_max = 150local hunger_rate = 1.7local scale = 0.9local speed = 1.1inst.AnimState:SetBuild("gir_dog")inst.strength="dog"inst.Transform:SetScale(scale,scale,scale)inst.replica.hunger:SetRate(hunger_rate*TUNING.WILSON_HUNGER_RATE)inst.components.combat.damagemultiplier = damage_multinst.components.locomotor.walkspeed = (TUNING.WILSON_WALK_SPEED * speed)inst.components.locomotor.runspeed = (TUNING.WILSON_RUN_SPEED * speed)inst.replica.sanity.dapperness = 0local health_percent = inst.replica.health:GetPercent()inst.replica.health:SetMaxHealth(health_max)inst.replica.health:SetPercent(health_percent, true)elseif (inst.strength=="dog" and inst.replica.sanity.current < 85) theninst.strength="mighty"elseif (inst.strength=="dog" and inst.replica.sanity.current > 85) theninst.strength="normal"endendendend

 

Combat Replica does not have a damage multiplier and locomoter doesn't have a replica so for those you will need to be creative in the way in which you adjust them.

Edited by Kzisor

Share this post


Link to post
Share on other sites
Purswader    7

@Kzisor, doesn't seem to work, i even tried

local function OnKeyPressed(inst, data)if data.player == ThePlayer thenif data.key == KEY_T thenprint("test")endendend

and there was no output :(

Share this post


Link to post
Share on other sites
Kzisor    1060

@Kzisor, doesn't seem to work, i even tried

local function OnKeyPressed(inst, data)if data.player == ThePlayer thenif data.key == KEY_T thenprint("test")endendend

and there was no output :(

 

Post your entire gir.lua file for me so I can see what it looks like. You should at least be getting output from print. Remember that you still need to assign the keyhandler component to gir.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this