Why won't my Crates and Boxes Stack?
Soul_Rider
Mod Bean Join Date: 2004-06-19 Member: 29388Members, Constellation, Squad Five Blue
This will probably get a bit code heavy. There is probably some very simple thing I am not taking into account, but this has been bugging me for 3 months now, so time to get some help :)
Here is the video of the problem...
<center><object width="450" height="356"><param name="movie" value="http://www.youtube.com/v/mVTl52RoITg"></param><embed src="http://www.youtube.com/v/mVTl52RoITg" type="application/x-shockwave-flash" width="450" height="356"></embed></object></center>
Here is the code from Crate.lua:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>// ======= Copyright © 2003-2012, Unknown Worlds Entertainment, Inc. All rights reserved. =======
//
// lua\Crate.lua
//
// Created by: Andy Soul Rider Wilson for GorgeCraft Mod
//
// ========= For more information, visit us at <a href="http://www.unknownworlds.com" target="_blank">http://www.unknownworlds.com</a> =====================
Script.Load("lua/OwnerMixin.lua")
Script.Load("lua/TeamMixin.lua")
Script.Load("lua/ClogFallMixin.lua")
Script.Load("lua/DigestMixin.lua")
Script.Load("lua/TechMixin.lua")
Script.Load("lua/EntityChangeMixin.lua")
Script.Load("lua/TargetMixin.lua")
local Shared_GetModel = Shared.GetModel
class 'Crate' (Actor)
Crate.kMapName = "crate"
Crate.kModelName = PrecacheAsset("models/props/refinery/refinery_crate_02.model")
local networkVars = { }
/*Crate.kXExtents = .8
Crate.kYExtents = 1.0
Crate.kZExtents = .3*/
Crate.kRadius = 0.75
// crates take maximum X damage per attack (prevents grenades being too effectfive against them), unless the attack is not a of type Flame)
Crate.kMaxShockDamage = 50
AddMixinNetworkVars(TechMixin, networkVars)
AddMixinNetworkVars(TeamMixin, networkVars)
AddMixinNetworkVars(LiveMixin, networkVars)
AddMixinNetworkVars(GameEffectsMixin, networkVars)
function Crate:OnCreate()
Actor.OnCreate(self)
self.boneCoords = CoordsArray()
InitMixin(self, TechMixin)
InitMixin(self, TeamMixin)
InitMixin(self, LiveMixin)
InitMixin(self, GameEffectsMixin)
InitMixin(self, TeamMixin)
InitMixin(self, TargetMixin)
if Server then
InitMixin(self, OwnerMixin)
InitMixin(self, ClogFallMixin)
InitMixin(self, DigestMixin)
InitMixin(self, EntityChangeMixin)
//InitMixin(self, GorgeStructureMixin)
self:SetUpdates(false)
elseif Client then
self:SetUpdates(true)
end
end
function Crate:OnInitialized()
self:CreatePhysics()
if Server then
local mask = bit.bor(kRelevantToTeam1Unit, kRelevantToTeam2Unit, kRelevantToReadyRoom)
if sighted or self:GetTeamNumber() == 1 then
mask = bit.bor(mask, kRelevantToTeam1Commander)
elseif self:GetTeamNumber() == 2 then
mask = bit.bor(mask, kRelevantToTeam2Commander)
end
self:SetExcludeRelevancyMask( mask )
end
end
function Crate:CreatePhysics()
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self.physicsModel = nil
end
//local crateExtents = LookupTechData(self:GetTechId(), kTechDataMaxExtents)
//self.physicsModel = Shared.CreatePhysicsBoxBody(true, crateExtents, 20, self:GetCoords())
self.physicsModel = Shared.CreatePhysicsSphereBody(true, Crate.kRadius, 20, self:GetCoords())
self.physicsModel:SetGroup(PhysicsGroup.BigStructuresGroup)
self.physicsModel:SetEntity(self)
self.physicsModel:SetPhysicsType(CollisionObject.Static)
end
function Crate:OnDestroy()
if self._renderModel ~= nil then
Client.DestroyRenderModel(self._renderModel)
self._renderModel = nil
end
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self.physicsModel = nil
end
end
function Crate:SpaceClearForEntity(location)
return true
end
function Crate:GetIsFlameAble()
return true
end
function Crate:GetShowCrossHairText(toPlayer)
return false
end
function Crate:GetCanBeHealedOverride()
return false
end
function Crate:SetCoords(coords)
if self.physicsModel then
self.physicsModel:SetBoneCoords(coords, self.boneCoords)
end
if self._renderModel then
self._renderModel:SetCoords(coords)
end
Entity.SetCoords(self, coords)
end
function Crate:SetOrigin(origin)
local newCoords = self:GetCoords()
newCoords.origin = origin
if self.physicsModel then
self.physicsModel:SetBoneCoords(newCoords, CoordsArray())
end
if self._renderModel then
self._renderModel:SetCoords(newCoords)
end
Entity.SetOrigin(self, origin)
end
function Crate:GetModelOrigin()
return self:GetOrigin()
end
if Server then
function Crate:SetGameEffectMask(gameEffect, state)
if gameEffect == kGameEffect.OnFire then
if state == true then
self:SetUpdates(true)
elseif not self:GetIsFalling() then
self:SetUpdates(false)
end
end
end
function Crate:OnClogFall()
self:SetUpdates(true)
end
function Crate:OnClogFallDone()
if not self:GetIsOnFire() then
self:SetUpdates(false)
end
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self:CreatePhysics()
end
end
// simple solution for now to avoid griefing
function Crate:GetCanDiggest(player)
return player:GetIsAlive() and player:GetTeamNumber() == self:GetTeamNumber()
end
function Crate:OnKill()
self:TriggerEffects("death")
DestroyEntity(self)
end
function Crate:GetSendDeathMessageOverride()
return false
end
function Crate:OnCreatedByGorge(gorge)
self:TriggerEffects("spawn", {effecthostcoords = self:GetCoords()})
self:TriggerEffects("clog_slime")
end
elseif Client then
function Crate:GetShowHealthCircle()
return false
end
function Crate:OnUpdateRender()
end
end
function Crate:OnUpdate(deltaTime)
Actor.OnUpdate(self, deltaTime)
if self.physicsModel then
if Client and self:GetOrigin() ~= self.storedOrigin then
self:CreatePhysics()
self.storedOrigin = self:GetOrigin()
end
else
self:CreatePhysics()
end
if Client then
if self._renderModel then
self._renderModel:SetCoords(self:GetCoords())
//DebugCapsule(self:GetOrigin(), self:GetOrigin(), Crate.kRadius, 0, 0.03)
else
self._renderModel = Client.CreateRenderModel(RenderScene.Zone_Default)
self._renderModel:SetModel(Shared.GetModelIndex(Crate.kModelName))
end
end
end
function Crate:GetEffectParams(tableParams)
// Only override if not specified
if not tableParams[kEffectFilterClassName] and self.GetClassName then
tableParams[kEffectFilterClassName] = self:GetClassName()
end
if not tableParams[kEffectHostCoords] and self.GetCoords then
tableParams[kEffectHostCoords] = Coords.GetTranslation( self:GetOrigin() )
end
end
function Crate:ComputeDamageOverride(attacker, damage, damageType, time)
if damageType ~= kDamageType.Flame and damage >= Crate.kMaxShockDamage then
self:TriggerEffects("spawn", {effecthostcoords = self:GetCoords()})
damage = Crate.kMaxShockDamage
end
return damage
end
Shared.LinkClassToMap("Crate", Crate.kMapName, networkVars)</div>
There are 1 or two minor changes to the Clog code. I have used box extents and have tried the radius method as used by the Clog, you can see the commented out lines where I've switched between the 2 for testing. Here is the CrateAbility.lua code:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>// ======= Copyright © 2003-2011, Unknown Worlds Entertainment, Inc. All rights reserved. =======
//
// lua\Weapons\Alien\CrateAbility.lua
//
// Created by: Andy Soul Rider Wilson for GorgeCraft Mod
//
// ========= For more information, visit us at <a href="http://www.unknownworlds.com" target="_blank">http://www.unknownworlds.com</a> =====================
Script.Load("lua/Weapons/Alien/StructureAbility.lua")
class 'CrateAbility' (StructureAbility)
local kMinDistance = 0.1
local kVerticalMinDistance = 0.1
local kCrateOffset = 0.1
function CrateAbility:OverrideInfestationCheck(trace)
if trace.entity and trace.entity:isa("Crate") then
return true
end
return false
end
function CrateAbility:GetIsPositionValid(position, player)
/*local valid = true
local entities = GetEntitiesWithinRange("ScriptActor", position, kVerticalMinDistance)
Shared.SortEntitiesByDistance(position, entities)
for _, entity in ipairs(entities) do
if not entity:isa("Infestation") and not entity == player then
local closestPoint = entity:GetOrigin()
local fromStructure = position - closestPoint
local dotProduct = entity:GetCoords().yAxis:DotProduct(fromStructure)
// check horizontal distance (don't allow build on top of the structure)
valid = ( math.abs( fromStructure:GetLength() ) > kMinDistance and dotProduct < kMinDistance )
break
end
end*/
return true
end
function CrateAbility:GetEnergyCost(player)
return kDropCrateEnergyCost
end
function CrateAbility:GetDropRange()
return kGCDropRange
end
function CrateAbility:GetPrimaryAttackDelay()
return 1.0
end
function CrateAbility:GetIconOffsetY(secondary)
return kAbilityOffset.Hydra
end
function CrateAbility:GetGhostModelName(ability)
return Crate.kModelName
end
function CrateAbility:GetDropStructureId()
return kTechId.Crate
end
function CrateAbility:GetSuffixName()
return "crate"
end
function CrateAbility:GetDropClassName()
return "Crate"
end
function CrateAbility:GetDropMapName()
return Crate.kMapName
end</div>
Note I've coded out the positioning code that stops you from building on top of the structure, but still nothing works....
Here is the code from TechData.lua.....
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1--> { [kTechDataId] = kTechId.Clog, [kTechDataAllowConsumeDrop] = true, [kTechDataAllowStacking] = true, [kTechDataMapName] = Clog.kMapName, [kTechDataDisplayName] = "CLOG", [kTechDataCostKey] = kClogCost, [kTechDataMaxHealth] = kClogHealth, [kTechDataMaxArmor] = kClogArmor, [kTechDataModel] = Clog.kModelName, [kTechDataRequiresInfestation] = false, [kTechDataPointValue] = kClogPointValue },
{ [kTechDataId] = kTechId.Crate, [kTechDataAllowConsumeDrop] = true, [kTechDataAllowStacking] = true, [kTechDataMapName] = Crate.kMapName, [kTechDataDisplayName] = "CRATE", [kTechDataCostKey] = kCrateCost, [kTechDataMaxHealth] = kCrateHealth, [kTechDataMaxArmor] = kCrateArmor, [kTechDataModel] = Crate.kModelName, [kTechDataRequiresInfestation] = false, [kTechDataMaxExtents] = Vector(Crate.kXExtents, Crate.kYExtents, Crate.kZExtents), [kTechDataPointValue] = kCratePointValue },
{ [kTechDataId] = kTechId.Box, [kTechDataAllowConsumeDrop] = true, [kTechDataAllowStacking] = true, [kTechDataMapName] = Box.kMapName, [kTechDataDisplayName] = "BOX", [kTechDataCostKey] = kBoxCost, [kTechDataMaxHealth] = kBoxHealth, [kTechDataMaxArmor] = kBoxArmor, [kTechDataModel] = Box.kModelName, [kTechDataRequiresInfestation] = false, [kTechDataMaxExtents] = Vector(Box.kXExtents, Box.kYExtents, Box.kZExtents), [kTechDataPointValue] = kBoxPointValue },<!--c2--></div><!--ec2-->
Crates and Boxes can be consumed, but they can't be stacked. Where is the code coming from that is breaking this? Or what am I overlooking in my implementation?
Here is the Box.lua code, followed by the BoxAbility.lua code:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>// ======= Copyright © 2003-2012, Unknown Worlds Entertainment, Inc. All rights reserved. =======
//
// lua\Box.lua
//
// Created by: Andy Soul Rider Wilson for GorgeCraft Mod
//
// ========= For more information, visit us at <a href="http://www.unknownworlds.com" target="_blank">http://www.unknownworlds.com</a> =====================
Script.Load("lua/OwnerMixin.lua")
Script.Load("lua/TeamMixin.lua")
Script.Load("lua/ClogFallMixin.lua")
Script.Load("lua/DigestMixin.lua")
Script.Load("lua/TechMixin.lua")
Script.Load("lua/EntityChangeMixin.lua")
//Script.Load("lua/GorgeStructureMixin.lua")
Script.Load("lua/TargetMixin.lua")
local Shared_GetModel = Shared.GetModel
class 'Box' (Actor)
Box.kMapName = "box"
Box.kModelName = PrecacheAsset("models/props/generic/generic_crate_01.model")
local networkVars = { }
Box.kXExtents = .8
Box.kYExtents = 1.0
Box.kZExtents = .3
//Box.kRadius = 0.75
// boxs take maximum X damage per attack (prevents grenades being too effectfive against them), unless the attack is not a of type Flame)
Box.kMaxShockDamage = 50
AddMixinNetworkVars(TechMixin, networkVars)
AddMixinNetworkVars(TeamMixin, networkVars)
AddMixinNetworkVars(LiveMixin, networkVars)
AddMixinNetworkVars(GameEffectsMixin, networkVars)
function Box:OnCreate()
Actor.OnCreate(self)
self.boneCoords = CoordsArray()
InitMixin(self, TechMixin)
InitMixin(self, TeamMixin)
InitMixin(self, LiveMixin)
InitMixin(self, GameEffectsMixin)
InitMixin(self, TeamMixin)
InitMixin(self, TargetMixin)
InitMixin(self, EntityChangeMixin)
if Server then
InitMixin(self, OwnerMixin)
InitMixin(self, ClogFallMixin)
InitMixin(self, DigestMixin)
//InitMixin(self, GorgeStructureMixin)
self:SetUpdates(false)
elseif Client then
self:SetUpdates(true)
end
end
function Box:OnInitialized()
self:CreatePhysics()
if Server then
local mask = bit.bor(kRelevantToTeam1Unit, kRelevantToTeam2Unit, kRelevantToReadyRoom)
if sighted or self:GetTeamNumber() == 1 then
mask = bit.bor(mask, kRelevantToTeam1Commander)
elseif self:GetTeamNumber() == 2 then
mask = bit.bor(mask, kRelevantToTeam2Commander)
end
self:SetExcludeRelevancyMask( mask )
end
end
function Box:CreatePhysics()
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self.physicsModel = nil
end
local boxExtents = LookupTechData(self:GetTechId(), kTechDataMaxExtents)
self.physicsModel = Shared.CreatePhysicsBoxBody(true, boxExtents, 20, self:GetCoords())
self.physicsModel:SetGroup(PhysicsGroup.MediumStructuresGroup)
self.physicsModel:SetEntity(self)
self.physicsModel:SetPhysicsType(CollisionObject.Static)
end
function Box:OnDestroy()
if self._renderModel ~= nil then
Client.DestroyRenderModel(self._renderModel)
self._renderModel = nil
end
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self.physicsModel = nil
end
end
function Box:SpaceClearForEntity(location)
return true
end
function Box:GetIsFlameAble()
return true
end
function Box:GetShowCrossHairText(toPlayer)
return false
end
function Box:GetCanBeHealedOverride()
return false
end
function Box:SetCoords(coords)
if self.physicsModel then
self.physicsModel:SetBoneCoords(coords, self.boneCoords)
end
if self._renderModel then
self._renderModel:SetCoords(coords)
end
Entity.SetCoords(self, coords)
end
function Box:SetOrigin(origin)
local newCoords = self:GetCoords()
newCoords.origin = origin
if self.physicsModel then
self.physicsModel:SetBoneCoords(newCoords, CoordsArray())
end
if self._renderModel then
self._renderModel:SetCoords(newCoords)
end
Entity.SetOrigin(self, origin)
end
function Box:GetModelOrigin()
return self:GetOrigin()
end
if Server then
function Box:SetGameEffectMask(gameEffect, state)
if gameEffect == kGameEffect.OnFire then
if state == true then
self:SetUpdates(true)
elseif not self:GetIsFalling() then
self:SetUpdates(false)
end
end
end
function Box:OnClogFall()
self:SetUpdates(true)
end
function Box:OnClogFallDone()
if not self:GetIsOnFire() then
self:SetUpdates(false)
end
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self:CreatePhysics()
end
end
// simple solution for now to avoid griefing
function Box:GetCanDiggest(player)
return player:GetIsAlive() and player:GetTeamNumber() == self:GetTeamNumber()
end
function Box:OnKill()
self:TriggerEffects("death")
DestroyEntity(self)
end
function Box:GetSendDeathMessageOverride()
return false
end
function Box:OnCreatedByGorge(gorge)
self:TriggerEffects("spawn", {effecthostcoords = self:GetCoords()})
self:TriggerEffects("clog_slime")
end
elseif Client then
function Box:GetShowHealthCircle()
return false
end
function Box:OnUpdateRender()
end
end
function Box:OnUpdate(deltaTime)
Actor.OnUpdate(self, deltaTime)
if self.physicsModel then
if Client and self:GetOrigin() ~= self.storedOrigin then
self:CreatePhysics()
self.storedOrigin = self:GetOrigin()
end
else
self:CreatePhysics()
end
if Client then
if self._renderModel then
self._renderModel:SetCoords(self:GetCoords())
//DebugCapsule(self:GetOrigin(), self:GetOrigin(), Box.kRadius, 0, 0.03)
else
self._renderModel = Client.CreateRenderModel(RenderScene.Zone_Default)
self._renderModel:SetModel(Shared.GetModelIndex(Box.kModelName))
end
end
end
function Box:GetEffectParams(tableParams)
// Only override if not specified
if not tableParams[kEffectFilterClassName] and self.GetClassName then
tableParams[kEffectFilterClassName] = self:GetClassName()
end
if not tableParams[kEffectHostCoords] and self.GetCoords then
tableParams[kEffectHostCoords] = Coords.GetTranslation( self:GetOrigin() )
end
end
function Box:ComputeDamageOverride(attacker, damage, damageType, time)
if damageType ~= kDamageType.Flame and damage >= Box.kMaxShockDamage then
self:TriggerEffects("spawn", {effecthostcoords = self:GetCoords()})
damage = Box.kMaxShockDamage
end
return damage
end
Shared.LinkClassToMap("Box", Box.kMapName, networkVars)</div>
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>// ======= Copyright © 2003-2011, Unknown Worlds Entertainment, Inc. All rights reserved. =======
//
// lua\Weapons\Alien\BoxAbility.lua
//
// Created by: Andy Soul Rider Wilson for GorgeCraft Mod
//
// ========= For more information, visit us at <a href="http://www.unknownworlds.com" target="_blank">http://www.unknownworlds.com</a> =====================
Script.Load("lua/Weapons/Alien/StructureAbility.lua")
class 'BoxAbility' (StructureAbility)
local kMinDistance = 1
local kVerticalMinDistance = 1
local kBoxOffset = 0.1
function BoxAbility:OverrideInfestationCheck(trace)
if trace.entity and trace.entity:isa("Box") then
return true
end
return false
end
function BoxAbility:GetIsPositionValid(position, player)
local valid = true
local entities = GetEntitiesWithinRange("ScriptActor", position, kVerticalMinDistance)
Shared.SortEntitiesByDistance(position, entities)
for _, entity in ipairs(entities) do
if not entity:isa("Infestation") and not entity == player then
local closestPoint = entity:GetOrigin()
local fromStructure = position - closestPoint
local dotProduct = entity:GetCoords().yAxis:DotProduct(fromStructure)
// check horizontal distance (don't allow build on top of the structure)
//valid = ( math.abs( fromStructure:GetLength() ) > kMinDistance and dotProduct < kMinDistance ) or dotProduct > kVerticalMinDistance
break
end
end
return valid
end
function BoxAbility:GetEnergyCost(player)
return kDropBoxEnergyCost
end
function BoxAbility:GetDropRange()
return kGCDropRange
end
function BoxAbility:GetPrimaryAttackDelay()
return 1.0
end
function BoxAbility:GetIconOffsetY(secondary)
return kAbilityOffset.Hydra
end
function BoxAbility:GetGhostModelName(ability)
return Box.kModelName
end
function BoxAbility:GetDropStructureId()
return kTechId.Box
end
function BoxAbility:GetSuffixName()
return "box"
end
function BoxAbility:GetDropClassName()
return "Box"
end
function BoxAbility:GetDropMapName()
return Box.kMapName
end</div>
Any help is greatly appreciated. As you can see I have tried differring approaches throughout both codes to solve the problem, but nothing gives.... Any Help is greatly appreciated.
<!--coloro:orange--><span style="color:orange"><!--/coloro--><sup>Changed <strike>all code tags</strike> all but techdata.lua to codebox for easier reading. - Angelusz</sup><!--colorc--></span><!--/colorc-->
Thanks Angelusz, I didn't know codebox existed on these forums..
Here is the video of the problem...
<center><object width="450" height="356"><param name="movie" value="http://www.youtube.com/v/mVTl52RoITg"></param><embed src="http://www.youtube.com/v/mVTl52RoITg" type="application/x-shockwave-flash" width="450" height="356"></embed></object></center>
Here is the code from Crate.lua:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>// ======= Copyright © 2003-2012, Unknown Worlds Entertainment, Inc. All rights reserved. =======
//
// lua\Crate.lua
//
// Created by: Andy Soul Rider Wilson for GorgeCraft Mod
//
// ========= For more information, visit us at <a href="http://www.unknownworlds.com" target="_blank">http://www.unknownworlds.com</a> =====================
Script.Load("lua/OwnerMixin.lua")
Script.Load("lua/TeamMixin.lua")
Script.Load("lua/ClogFallMixin.lua")
Script.Load("lua/DigestMixin.lua")
Script.Load("lua/TechMixin.lua")
Script.Load("lua/EntityChangeMixin.lua")
Script.Load("lua/TargetMixin.lua")
local Shared_GetModel = Shared.GetModel
class 'Crate' (Actor)
Crate.kMapName = "crate"
Crate.kModelName = PrecacheAsset("models/props/refinery/refinery_crate_02.model")
local networkVars = { }
/*Crate.kXExtents = .8
Crate.kYExtents = 1.0
Crate.kZExtents = .3*/
Crate.kRadius = 0.75
// crates take maximum X damage per attack (prevents grenades being too effectfive against them), unless the attack is not a of type Flame)
Crate.kMaxShockDamage = 50
AddMixinNetworkVars(TechMixin, networkVars)
AddMixinNetworkVars(TeamMixin, networkVars)
AddMixinNetworkVars(LiveMixin, networkVars)
AddMixinNetworkVars(GameEffectsMixin, networkVars)
function Crate:OnCreate()
Actor.OnCreate(self)
self.boneCoords = CoordsArray()
InitMixin(self, TechMixin)
InitMixin(self, TeamMixin)
InitMixin(self, LiveMixin)
InitMixin(self, GameEffectsMixin)
InitMixin(self, TeamMixin)
InitMixin(self, TargetMixin)
if Server then
InitMixin(self, OwnerMixin)
InitMixin(self, ClogFallMixin)
InitMixin(self, DigestMixin)
InitMixin(self, EntityChangeMixin)
//InitMixin(self, GorgeStructureMixin)
self:SetUpdates(false)
elseif Client then
self:SetUpdates(true)
end
end
function Crate:OnInitialized()
self:CreatePhysics()
if Server then
local mask = bit.bor(kRelevantToTeam1Unit, kRelevantToTeam2Unit, kRelevantToReadyRoom)
if sighted or self:GetTeamNumber() == 1 then
mask = bit.bor(mask, kRelevantToTeam1Commander)
elseif self:GetTeamNumber() == 2 then
mask = bit.bor(mask, kRelevantToTeam2Commander)
end
self:SetExcludeRelevancyMask( mask )
end
end
function Crate:CreatePhysics()
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self.physicsModel = nil
end
//local crateExtents = LookupTechData(self:GetTechId(), kTechDataMaxExtents)
//self.physicsModel = Shared.CreatePhysicsBoxBody(true, crateExtents, 20, self:GetCoords())
self.physicsModel = Shared.CreatePhysicsSphereBody(true, Crate.kRadius, 20, self:GetCoords())
self.physicsModel:SetGroup(PhysicsGroup.BigStructuresGroup)
self.physicsModel:SetEntity(self)
self.physicsModel:SetPhysicsType(CollisionObject.Static)
end
function Crate:OnDestroy()
if self._renderModel ~= nil then
Client.DestroyRenderModel(self._renderModel)
self._renderModel = nil
end
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self.physicsModel = nil
end
end
function Crate:SpaceClearForEntity(location)
return true
end
function Crate:GetIsFlameAble()
return true
end
function Crate:GetShowCrossHairText(toPlayer)
return false
end
function Crate:GetCanBeHealedOverride()
return false
end
function Crate:SetCoords(coords)
if self.physicsModel then
self.physicsModel:SetBoneCoords(coords, self.boneCoords)
end
if self._renderModel then
self._renderModel:SetCoords(coords)
end
Entity.SetCoords(self, coords)
end
function Crate:SetOrigin(origin)
local newCoords = self:GetCoords()
newCoords.origin = origin
if self.physicsModel then
self.physicsModel:SetBoneCoords(newCoords, CoordsArray())
end
if self._renderModel then
self._renderModel:SetCoords(newCoords)
end
Entity.SetOrigin(self, origin)
end
function Crate:GetModelOrigin()
return self:GetOrigin()
end
if Server then
function Crate:SetGameEffectMask(gameEffect, state)
if gameEffect == kGameEffect.OnFire then
if state == true then
self:SetUpdates(true)
elseif not self:GetIsFalling() then
self:SetUpdates(false)
end
end
end
function Crate:OnClogFall()
self:SetUpdates(true)
end
function Crate:OnClogFallDone()
if not self:GetIsOnFire() then
self:SetUpdates(false)
end
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self:CreatePhysics()
end
end
// simple solution for now to avoid griefing
function Crate:GetCanDiggest(player)
return player:GetIsAlive() and player:GetTeamNumber() == self:GetTeamNumber()
end
function Crate:OnKill()
self:TriggerEffects("death")
DestroyEntity(self)
end
function Crate:GetSendDeathMessageOverride()
return false
end
function Crate:OnCreatedByGorge(gorge)
self:TriggerEffects("spawn", {effecthostcoords = self:GetCoords()})
self:TriggerEffects("clog_slime")
end
elseif Client then
function Crate:GetShowHealthCircle()
return false
end
function Crate:OnUpdateRender()
end
end
function Crate:OnUpdate(deltaTime)
Actor.OnUpdate(self, deltaTime)
if self.physicsModel then
if Client and self:GetOrigin() ~= self.storedOrigin then
self:CreatePhysics()
self.storedOrigin = self:GetOrigin()
end
else
self:CreatePhysics()
end
if Client then
if self._renderModel then
self._renderModel:SetCoords(self:GetCoords())
//DebugCapsule(self:GetOrigin(), self:GetOrigin(), Crate.kRadius, 0, 0.03)
else
self._renderModel = Client.CreateRenderModel(RenderScene.Zone_Default)
self._renderModel:SetModel(Shared.GetModelIndex(Crate.kModelName))
end
end
end
function Crate:GetEffectParams(tableParams)
// Only override if not specified
if not tableParams[kEffectFilterClassName] and self.GetClassName then
tableParams[kEffectFilterClassName] = self:GetClassName()
end
if not tableParams[kEffectHostCoords] and self.GetCoords then
tableParams[kEffectHostCoords] = Coords.GetTranslation( self:GetOrigin() )
end
end
function Crate:ComputeDamageOverride(attacker, damage, damageType, time)
if damageType ~= kDamageType.Flame and damage >= Crate.kMaxShockDamage then
self:TriggerEffects("spawn", {effecthostcoords = self:GetCoords()})
damage = Crate.kMaxShockDamage
end
return damage
end
Shared.LinkClassToMap("Crate", Crate.kMapName, networkVars)</div>
There are 1 or two minor changes to the Clog code. I have used box extents and have tried the radius method as used by the Clog, you can see the commented out lines where I've switched between the 2 for testing. Here is the CrateAbility.lua code:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>// ======= Copyright © 2003-2011, Unknown Worlds Entertainment, Inc. All rights reserved. =======
//
// lua\Weapons\Alien\CrateAbility.lua
//
// Created by: Andy Soul Rider Wilson for GorgeCraft Mod
//
// ========= For more information, visit us at <a href="http://www.unknownworlds.com" target="_blank">http://www.unknownworlds.com</a> =====================
Script.Load("lua/Weapons/Alien/StructureAbility.lua")
class 'CrateAbility' (StructureAbility)
local kMinDistance = 0.1
local kVerticalMinDistance = 0.1
local kCrateOffset = 0.1
function CrateAbility:OverrideInfestationCheck(trace)
if trace.entity and trace.entity:isa("Crate") then
return true
end
return false
end
function CrateAbility:GetIsPositionValid(position, player)
/*local valid = true
local entities = GetEntitiesWithinRange("ScriptActor", position, kVerticalMinDistance)
Shared.SortEntitiesByDistance(position, entities)
for _, entity in ipairs(entities) do
if not entity:isa("Infestation") and not entity == player then
local closestPoint = entity:GetOrigin()
local fromStructure = position - closestPoint
local dotProduct = entity:GetCoords().yAxis:DotProduct(fromStructure)
// check horizontal distance (don't allow build on top of the structure)
valid = ( math.abs( fromStructure:GetLength() ) > kMinDistance and dotProduct < kMinDistance )
break
end
end*/
return true
end
function CrateAbility:GetEnergyCost(player)
return kDropCrateEnergyCost
end
function CrateAbility:GetDropRange()
return kGCDropRange
end
function CrateAbility:GetPrimaryAttackDelay()
return 1.0
end
function CrateAbility:GetIconOffsetY(secondary)
return kAbilityOffset.Hydra
end
function CrateAbility:GetGhostModelName(ability)
return Crate.kModelName
end
function CrateAbility:GetDropStructureId()
return kTechId.Crate
end
function CrateAbility:GetSuffixName()
return "crate"
end
function CrateAbility:GetDropClassName()
return "Crate"
end
function CrateAbility:GetDropMapName()
return Crate.kMapName
end</div>
Note I've coded out the positioning code that stops you from building on top of the structure, but still nothing works....
Here is the code from TechData.lua.....
<!--c1--><div class='codetop'>CODE</div><div class='codemain'><!--ec1--> { [kTechDataId] = kTechId.Clog, [kTechDataAllowConsumeDrop] = true, [kTechDataAllowStacking] = true, [kTechDataMapName] = Clog.kMapName, [kTechDataDisplayName] = "CLOG", [kTechDataCostKey] = kClogCost, [kTechDataMaxHealth] = kClogHealth, [kTechDataMaxArmor] = kClogArmor, [kTechDataModel] = Clog.kModelName, [kTechDataRequiresInfestation] = false, [kTechDataPointValue] = kClogPointValue },
{ [kTechDataId] = kTechId.Crate, [kTechDataAllowConsumeDrop] = true, [kTechDataAllowStacking] = true, [kTechDataMapName] = Crate.kMapName, [kTechDataDisplayName] = "CRATE", [kTechDataCostKey] = kCrateCost, [kTechDataMaxHealth] = kCrateHealth, [kTechDataMaxArmor] = kCrateArmor, [kTechDataModel] = Crate.kModelName, [kTechDataRequiresInfestation] = false, [kTechDataMaxExtents] = Vector(Crate.kXExtents, Crate.kYExtents, Crate.kZExtents), [kTechDataPointValue] = kCratePointValue },
{ [kTechDataId] = kTechId.Box, [kTechDataAllowConsumeDrop] = true, [kTechDataAllowStacking] = true, [kTechDataMapName] = Box.kMapName, [kTechDataDisplayName] = "BOX", [kTechDataCostKey] = kBoxCost, [kTechDataMaxHealth] = kBoxHealth, [kTechDataMaxArmor] = kBoxArmor, [kTechDataModel] = Box.kModelName, [kTechDataRequiresInfestation] = false, [kTechDataMaxExtents] = Vector(Box.kXExtents, Box.kYExtents, Box.kZExtents), [kTechDataPointValue] = kBoxPointValue },<!--c2--></div><!--ec2-->
Crates and Boxes can be consumed, but they can't be stacked. Where is the code coming from that is breaking this? Or what am I overlooking in my implementation?
Here is the Box.lua code, followed by the BoxAbility.lua code:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>// ======= Copyright © 2003-2012, Unknown Worlds Entertainment, Inc. All rights reserved. =======
//
// lua\Box.lua
//
// Created by: Andy Soul Rider Wilson for GorgeCraft Mod
//
// ========= For more information, visit us at <a href="http://www.unknownworlds.com" target="_blank">http://www.unknownworlds.com</a> =====================
Script.Load("lua/OwnerMixin.lua")
Script.Load("lua/TeamMixin.lua")
Script.Load("lua/ClogFallMixin.lua")
Script.Load("lua/DigestMixin.lua")
Script.Load("lua/TechMixin.lua")
Script.Load("lua/EntityChangeMixin.lua")
//Script.Load("lua/GorgeStructureMixin.lua")
Script.Load("lua/TargetMixin.lua")
local Shared_GetModel = Shared.GetModel
class 'Box' (Actor)
Box.kMapName = "box"
Box.kModelName = PrecacheAsset("models/props/generic/generic_crate_01.model")
local networkVars = { }
Box.kXExtents = .8
Box.kYExtents = 1.0
Box.kZExtents = .3
//Box.kRadius = 0.75
// boxs take maximum X damage per attack (prevents grenades being too effectfive against them), unless the attack is not a of type Flame)
Box.kMaxShockDamage = 50
AddMixinNetworkVars(TechMixin, networkVars)
AddMixinNetworkVars(TeamMixin, networkVars)
AddMixinNetworkVars(LiveMixin, networkVars)
AddMixinNetworkVars(GameEffectsMixin, networkVars)
function Box:OnCreate()
Actor.OnCreate(self)
self.boneCoords = CoordsArray()
InitMixin(self, TechMixin)
InitMixin(self, TeamMixin)
InitMixin(self, LiveMixin)
InitMixin(self, GameEffectsMixin)
InitMixin(self, TeamMixin)
InitMixin(self, TargetMixin)
InitMixin(self, EntityChangeMixin)
if Server then
InitMixin(self, OwnerMixin)
InitMixin(self, ClogFallMixin)
InitMixin(self, DigestMixin)
//InitMixin(self, GorgeStructureMixin)
self:SetUpdates(false)
elseif Client then
self:SetUpdates(true)
end
end
function Box:OnInitialized()
self:CreatePhysics()
if Server then
local mask = bit.bor(kRelevantToTeam1Unit, kRelevantToTeam2Unit, kRelevantToReadyRoom)
if sighted or self:GetTeamNumber() == 1 then
mask = bit.bor(mask, kRelevantToTeam1Commander)
elseif self:GetTeamNumber() == 2 then
mask = bit.bor(mask, kRelevantToTeam2Commander)
end
self:SetExcludeRelevancyMask( mask )
end
end
function Box:CreatePhysics()
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self.physicsModel = nil
end
local boxExtents = LookupTechData(self:GetTechId(), kTechDataMaxExtents)
self.physicsModel = Shared.CreatePhysicsBoxBody(true, boxExtents, 20, self:GetCoords())
self.physicsModel:SetGroup(PhysicsGroup.MediumStructuresGroup)
self.physicsModel:SetEntity(self)
self.physicsModel:SetPhysicsType(CollisionObject.Static)
end
function Box:OnDestroy()
if self._renderModel ~= nil then
Client.DestroyRenderModel(self._renderModel)
self._renderModel = nil
end
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self.physicsModel = nil
end
end
function Box:SpaceClearForEntity(location)
return true
end
function Box:GetIsFlameAble()
return true
end
function Box:GetShowCrossHairText(toPlayer)
return false
end
function Box:GetCanBeHealedOverride()
return false
end
function Box:SetCoords(coords)
if self.physicsModel then
self.physicsModel:SetBoneCoords(coords, self.boneCoords)
end
if self._renderModel then
self._renderModel:SetCoords(coords)
end
Entity.SetCoords(self, coords)
end
function Box:SetOrigin(origin)
local newCoords = self:GetCoords()
newCoords.origin = origin
if self.physicsModel then
self.physicsModel:SetBoneCoords(newCoords, CoordsArray())
end
if self._renderModel then
self._renderModel:SetCoords(newCoords)
end
Entity.SetOrigin(self, origin)
end
function Box:GetModelOrigin()
return self:GetOrigin()
end
if Server then
function Box:SetGameEffectMask(gameEffect, state)
if gameEffect == kGameEffect.OnFire then
if state == true then
self:SetUpdates(true)
elseif not self:GetIsFalling() then
self:SetUpdates(false)
end
end
end
function Box:OnClogFall()
self:SetUpdates(true)
end
function Box:OnClogFallDone()
if not self:GetIsOnFire() then
self:SetUpdates(false)
end
if self.physicsModel then
Shared.DestroyCollisionObject(self.physicsModel)
self:CreatePhysics()
end
end
// simple solution for now to avoid griefing
function Box:GetCanDiggest(player)
return player:GetIsAlive() and player:GetTeamNumber() == self:GetTeamNumber()
end
function Box:OnKill()
self:TriggerEffects("death")
DestroyEntity(self)
end
function Box:GetSendDeathMessageOverride()
return false
end
function Box:OnCreatedByGorge(gorge)
self:TriggerEffects("spawn", {effecthostcoords = self:GetCoords()})
self:TriggerEffects("clog_slime")
end
elseif Client then
function Box:GetShowHealthCircle()
return false
end
function Box:OnUpdateRender()
end
end
function Box:OnUpdate(deltaTime)
Actor.OnUpdate(self, deltaTime)
if self.physicsModel then
if Client and self:GetOrigin() ~= self.storedOrigin then
self:CreatePhysics()
self.storedOrigin = self:GetOrigin()
end
else
self:CreatePhysics()
end
if Client then
if self._renderModel then
self._renderModel:SetCoords(self:GetCoords())
//DebugCapsule(self:GetOrigin(), self:GetOrigin(), Box.kRadius, 0, 0.03)
else
self._renderModel = Client.CreateRenderModel(RenderScene.Zone_Default)
self._renderModel:SetModel(Shared.GetModelIndex(Box.kModelName))
end
end
end
function Box:GetEffectParams(tableParams)
// Only override if not specified
if not tableParams[kEffectFilterClassName] and self.GetClassName then
tableParams[kEffectFilterClassName] = self:GetClassName()
end
if not tableParams[kEffectHostCoords] and self.GetCoords then
tableParams[kEffectHostCoords] = Coords.GetTranslation( self:GetOrigin() )
end
end
function Box:ComputeDamageOverride(attacker, damage, damageType, time)
if damageType ~= kDamageType.Flame and damage >= Box.kMaxShockDamage then
self:TriggerEffects("spawn", {effecthostcoords = self:GetCoords()})
damage = Box.kMaxShockDamage
end
return damage
end
Shared.LinkClassToMap("Box", Box.kMapName, networkVars)</div>
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>// ======= Copyright © 2003-2011, Unknown Worlds Entertainment, Inc. All rights reserved. =======
//
// lua\Weapons\Alien\BoxAbility.lua
//
// Created by: Andy Soul Rider Wilson for GorgeCraft Mod
//
// ========= For more information, visit us at <a href="http://www.unknownworlds.com" target="_blank">http://www.unknownworlds.com</a> =====================
Script.Load("lua/Weapons/Alien/StructureAbility.lua")
class 'BoxAbility' (StructureAbility)
local kMinDistance = 1
local kVerticalMinDistance = 1
local kBoxOffset = 0.1
function BoxAbility:OverrideInfestationCheck(trace)
if trace.entity and trace.entity:isa("Box") then
return true
end
return false
end
function BoxAbility:GetIsPositionValid(position, player)
local valid = true
local entities = GetEntitiesWithinRange("ScriptActor", position, kVerticalMinDistance)
Shared.SortEntitiesByDistance(position, entities)
for _, entity in ipairs(entities) do
if not entity:isa("Infestation") and not entity == player then
local closestPoint = entity:GetOrigin()
local fromStructure = position - closestPoint
local dotProduct = entity:GetCoords().yAxis:DotProduct(fromStructure)
// check horizontal distance (don't allow build on top of the structure)
//valid = ( math.abs( fromStructure:GetLength() ) > kMinDistance and dotProduct < kMinDistance ) or dotProduct > kVerticalMinDistance
break
end
end
return valid
end
function BoxAbility:GetEnergyCost(player)
return kDropBoxEnergyCost
end
function BoxAbility:GetDropRange()
return kGCDropRange
end
function BoxAbility:GetPrimaryAttackDelay()
return 1.0
end
function BoxAbility:GetIconOffsetY(secondary)
return kAbilityOffset.Hydra
end
function BoxAbility:GetGhostModelName(ability)
return Box.kModelName
end
function BoxAbility:GetDropStructureId()
return kTechId.Box
end
function BoxAbility:GetSuffixName()
return "box"
end
function BoxAbility:GetDropClassName()
return "Box"
end
function BoxAbility:GetDropMapName()
return Box.kMapName
end</div>
Any help is greatly appreciated. As you can see I have tried differring approaches throughout both codes to solve the problem, but nothing gives.... Any Help is greatly appreciated.
<!--coloro:orange--><span style="color:orange"><!--/coloro--><sup>Changed <strike>all code tags</strike> all but techdata.lua to codebox for easier reading. - Angelusz</sup><!--colorc--></span><!--/colorc-->
Thanks Angelusz, I didn't know codebox existed on these forums..
Comments
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'> // If it hits something, position on this surface (must be the world or another structure)
if trace.fraction < 1 then
if trace.entity == nil then
validPosition = true
elseif trace.entity:isa("Infestation") or trace.entity:isa("Clog") then
validPosition = true
end
displayOrigin = trace.endPoint
end</div>
validPosition is defined false on top of that function
Edit - Crates are now stacking, but their physics boxes are all over the place..... I can get say X and Y extents correct, then when I adjust the Z extent, the others go out of whack again, same for any combination in the 3, really wierd, haha.