Rick Posted December 29, 2009 Share Posted December 29, 2009 So my "model" is a character object. I have it basically like a pivot. I only really care about the position because I place a controller at the position of the object in the editor. My issue is that the first time I run it it doesn't set the controller position correction. What am I missing? require("scripts/class") local class=CreateClass(...) function class:InitDialog(grid) self.super:InitDialog(grid) group = grid:AddGroup("Character") group:AddProperty("model", PROPERTY_FILE, "GMF Files (*.gmf):gmf", "", "Model Files") group:AddProperty("controller_height", PROPERTY_FLOAT, "Controller Height") group:AddProperty("controller_radius", PROPERTY_FLOAT, "Controller Radius") group:AddProperty("controller_step_height", PROPERTY_FLOAT, "Controller Step Height") group:AddProperty("controller_max_slope", PROPERTY_FLOAT, "Controller Max Slope") group:Expand(1) end function class:CreateObject(model) local object=self.super:CreateObject(model) object.model = model local height = tonumber(object:GetKey("controller_height", "1.8")) local radius = tonumber(object:GetKey("controller_radius", "0.4")) local step = tonumber(object:GetKey("controller_step_height", "0.5")) local slope = tonumber(object:GetKey("controller_max_slope", "45.0")) object.oneTime = false object.controller = CreateController(height, radius, step, slope) object.controller:SetMass(1.0) EntityType(object.controller, 1) object.controller:SetPosition(object.model:GetPosition()) function object:SetKey(key,value) --Notify(key.." "..value) if key=="model" then else return self.super:SetKey(key,value) end return 1 end function object:GetKey(key,value) if key=="" then else return self.super:GetKey(key,value) end return value end function object:Update() if GetGlobalString("mode") == "GAME_MODE" then if object.oneTime == false then Notify("inside") object.oneTime = true object.controller:SetPosition(object.model:GetPosition()) end else -- constantly update the controller to the model in scene --object.controller:SetPosition(object.model:GetPosition()) end end Quote Link to comment Share on other sites More sharing options...
macklebee Posted December 29, 2009 Share Posted December 29, 2009 not really following what you are asking... when i place the model in the scene the controller is created at its location... and if i uncomment the setpostion in the update function it continues to follow it when i move it... Quote Win7 64bit / Intel i7-2600 CPU @ 3.9 GHz / 16 GB DDR3 / NVIDIA GeForce GTX 590 LE / 3DWS / BMX / Hexagon macklebee's channel Link to comment Share on other sites More sharing options...
Rick Posted December 29, 2009 Author Share Posted December 29, 2009 Now when I create a scene with a terrain and place the model the controller falls right through the terrain. What gives. The most frustrating thing about the new editor and lua is getting things to work the way you want in the editor vs when you run via game. So if you make that object if sits correctly where you place it? I assume you created this object then? What do your files that you created for this look like? I actually have to do "run game" once before it resets correctly and doesn't fall through. Maybe I'll try resyncing or something. Quote Link to comment Share on other sites More sharing options...
Rick Posted December 29, 2009 Author Share Posted December 29, 2009 Also, pressing the reset physics puts my controller at the origin. *sigh* Quote Link to comment Share on other sites More sharing options...
macklebee Posted December 29, 2009 Share Posted December 29, 2009 Now when I create a scene with a terrain and place the model the controller falls right through the terrain. What gives. The most frustrating thing about the new editor and lua is getting things to work the way you want in the editor vs when you run via game. So if you make that object if sits correctly where you place it? I assume you created this object then? What do your files that you created for this look like? I actually have to do "run game" once before it resets correctly and doesn't fall through. Maybe I'll try resyncing or something. whats frustrating is that lua worked better in multistate but Josh decided to listen to few people and changed it to singlestate... now standard scripted entities either do not work or only work inside the editor. not to mention all of the other issues that are rearing their ugly head since this update... like CreateController() or CreateFramewerk() not working except inside the editor... the problem you are facing is the same thing that I had already encountered a month ago when i did this exact same thing for multistate lua... the controller needs to be offset from the model half the height of the controller because it will spawn the middle of the controller in the middle of the model. So if your model is less than half the height of the controller to the ground it will create the controller below the terrain... and therefore the controller will fall thru the ground. Quote Win7 64bit / Intel i7-2600 CPU @ 3.9 GHz / 16 GB DDR3 / NVIDIA GeForce GTX 590 LE / 3DWS / BMX / Hexagon macklebee's channel Link to comment Share on other sites More sharing options...
Rick Posted December 29, 2009 Author Share Posted December 29, 2009 Oh yeah that's right. Thanks. I'll just uncomment the "editor" mode setting the position and call it good. I can't comment on the outside of the editor. Haven't tried that yet. Quote Link to comment Share on other sites More sharing options...
Josh Posted December 29, 2009 Share Posted December 29, 2009 For the crawler model, I ended up using the Reset() function to get around the problem of repositioning the controller. This is written for multistate Lua, so it needs some small changes to work: dofile("scripts/base.lua") dofile("scripts/math.lua") dofile("scripts/linkedlist.lua") AINodeScanRange=100 AnimationWalk=0 AnimationIdle=1 animspeed={} animspeed[AnimationWalk]=0.036 animspeed[AnimationIdle]=0.01 dummynode=LoadModel("abstract::info_ai_node.gmf") if dummynode~=nil then dummynode:Hide() end function Cleanup() if dummynode~=nil then dummynode:Free() dummynode=nil end end function Reset(model) local entity=entitytable[model] if entity==nil then return end entity.controller:SetPosition(Vec3(model.position.x,model.position.y+0.9,model.position.z)) entity.angle=model.rotation.y+180.0 model:SetTarget(nil,0) end function UnlockKeys(model) model:SetTarget(nil) end function SetKey(model,key,value) local entity=entitytable[model] if entity==nil then return 1 end if key=="enabled" then if entity.controller~=nil then if value=="0" then entity.controller:SetMass(0) else entity.controller:SetMass(10) end end end return base_SetKey(model,key,value) end function Spawn(model) local entity=base_Spawn(model) entity.angle=model.rotation.y entity.controller=CreateController(1.8,0.45,0.25,45) entity.controller:SetPosition(entity.model.position) entity.controller:SetRotation(entity.model.rotation) entity.controller:Move(Vec3(0,0.9,0)) entity.controller:SetCollisionType(1,0) entity.controller:SetMass(10) entity.currentanimation=0 if entity.model:CountAnimations()<2 then --LoadAnimation(entity.model,"abstract::actor_cartoon2.gmf") end function entity:ChooseNewNode(ainode) local nodes={} local i local count=0 local newtarget --Create a table of all AI nodes this node is connected to for i=0,15 do nodes[count]=ainode:GetTarget(i) if nodes[count]~=nil then if nodes[count]~=self.prevnode then --avoid doubling back count=count+1 end end end --Choose a random node if count>0 then newtarget=nodes[math.random(0,count-1)] self.model:SetTarget(newtarget,0) else --no node found, so let's just use the previous node --self.model:SetTarget(self.prevnode,0) self.model:SetTarget(nil,0) end --if ainode~=nil then self.prevnode=ainode --end end function entity:Update() local dx,dz,p local target local ainode local closestainode=nil local closestdistance=10000000.0 local perfectangle local noderadius local movement=0 target=self.model:GetTarget(0) --b=CurrentWorld().entities --If target is nil, we need to choose an AI node to move to if target==nil then if dummynode~=nil then for ainode in iterate(dummynode.reference.instances) do if ainode~=self.prevnode then if ainode:Hidden()==0 then d=EntityDistance(ainode,self.model) if d<AINodeScanRange then --dismiss nodes that are far away if PointVisible(self.model.aabb:Center(),ainode.mat:Translation(),0,COLLISION_AILINEOFSIGHT)==1 then --line-of-sight test if d<closestdistance then closestdistance=d closestainode=ainode end end end end end end --Found a valid AI node, so set the target if closestainode~=nil then self.model:SetTarget(closestainode,0) end end end --We have a target node to move to if target~=nil then --Figure out angle between actor and target dx=target.mat.tx-self.model.mat.tx dz=target.mat.tz-self.model.mat.tz perfectangle=math.deg(math.atan2(-dx,dz)) --Calculate angle between the actor and the target and adjust as necessary. --This provides a smoother more natural movement, and the character takes --the easiest path instead of pointing straight at the target node. local noderadius=tonumber(target:GetKey("radius","4.0")) local noderange=tonumber(target:GetKey("range","1.0")) --Get the distance between the projected entity vector and the node model:SetRotation(Vec3(0,self.angle,0),1) local d=LineCircleDistance(model.mat.tx,model.mat.tz,model.mat.tx+model.mat.kx*100.0,model.mat.tz+model.mat.kz*100.0,target.mat.tx,target.mat.tz,3.0,1,0) --If the distance is over the radius, increment the angle towards the node local turnradius = 1.0 turnradius = turnradius+clamp( 90.0*(1.0 - clamp( d/1.0,0 ,1) ),0,10 ) if math.abs(d)>noderadius then self.angle=IncAngle(perfectangle,self.angle,turnradius*AppSpeed()) end --Choose new node when target node is close enough --We only care about the 2D distance on the XZ plane if math.sqrt(dx*dx+dz*dz)<noderange then self:ChooseNewNode(target) end movement=2 self.currentanimation=0 else movement=0 self.currentanimation=1 end --Update the controller self.controller:Update(self.angle,movement,0,0,40,1) self.model:SetPosition(self.controller.position) self.model:SetRotation(self.controller.rotation) self.model:Move(Vec3(0,-0.9,0)) self.model:Turn(Vec3(0,180,0)) local frame=AppTime()*0.08 frame=math.mod(frame,130-70)+70 if EntityCulled(model,fw.Main.camera)==0 then self.model:Animate(frame,1,0,1) end end return entity end function Update(model) local entity for model,entity in pairs(entitytable) do if entity.model:Hidden()==0 then if entity.enabled~=0 then entity:Update() end end end end function Kill(model) local entity=entitytable[model] if entity~=nil then if entity.controller~=nil then entity.controller:Free() entity.controller=nil end end base_Kill(model) end Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Rick Posted December 29, 2009 Author Share Posted December 29, 2009 I just added 1/2 the controller height to the y position of the object. Since the object ends up being on the plane of the terrain this moves the controller up to the terrain level and it doesn't fall through anymore. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.