So what i'm trying to do is whenever a player switches to a weapon, draw a model on the persons player model for everyone to see it. I know it can be done, and I have an old way of doing it but it is very sloppy.
The old way was every time newWeapon:GetClass() == "weapon_mu_magnum" then it would buy and equip the model from the pointshop. This really renders the pointshop useless. I know there is a way of doing this, but after spending some hours looking over the pointshop code I can not figure out how to do it.
Can anyone help me out, I know it can be done just don't know how.
Thanks.
Anyone Got any idea on this? I know pointshop uses
[lua]
self.HoverModel = item_id
self.HoverModelClientsideModel = ClientsideModel(ITEM.Model, RENDERGROUP_OPAQUE)
self.HoverModelClientsideModel:SetNoDraw(true)
[/lua]
When replacing ITEM.Model with a Model file I just gives me a nil error.
then it uses
[lua]
hook.Add('PostPlayerDraw', 'PS_PostPlayerDraw', function(ply)
[/lua]
to modify the model which will need to be done in my case because the model is not in the right position.
I've implemented something like this in my own gamemode.
What I did is net.Broadcast when a player spawns, and give them a clientsidemodel weapon on every client, and set specific bones and positional and angular offsets in a table, that you can do yourself because it requires a bit of specific work. then I draw it with this function:
[code]function GM:PostPlayerDraw(ply)
if (ply == LocalPlayer():GetObserverTarget() and LocalPlayer():GetObserverMode() == OBS_MODE_IN_EYE) or
(ply == LocalPlayer() and !LocalPlayer():ShouldDrawLocalPlayer()) or
!ply:Alive() or !ply:Team() == TEAM_SURV then return end
if istable(ply.Weapons) then
for k, wep in pairs(ply:GetWeapons()) do
local slot = wep:GetSlot()
if slot and ply.Weapons[slot] then
for i=1,#ply.Weapons[slot] do
local wepData = ply.Weapons[slot][i]
if !(ply.Weapons[slot][i]:GetModel() ~= wep:GetModel() or (slot == 3 and wep.Ammo1 and wep:Ammo1() == 0) or wep == ply:GetActiveWeapon()) then
local pos, ang = Vector(), Angle()
if ply:LookupBone(wepData.bone) then pos, ang = ply:GetBonePosition(ply:LookupBone(wepData.bone)) end
pos = pos + (ang:Right() * wepData.pos.x)
pos = pos + (ang:Forward() * wepData.pos.y)
pos = pos + (ang:Up() * wepData.pos.z)
--Rotate bone angle with angle offsets. It must be in pitch, yaw, roll order.
ang:RotateAroundAxis(ang:Right(), wepData.ang.p)
ang:RotateAroundAxis(ang:Up(), wepData.ang.y)
ang:RotateAroundAxis(ang:Forward(), wepData.ang.r)
wepData:SetAngles(ang)
wepData:SetPos(pos)
wepData:SetRenderOrigin(pos)
wepData:SetRenderAngles(ang)
wepData:SetupBones()
wepData:DrawModel()
wepData:SetRenderOrigin()
wepData:SetRenderAngles()
wepData:SetModel(wep:GetModel() == "models/weapons/w_pist_elite.mdl" and "models/weapons/w_pist_elite_single.mdl" or wep:GetModel())
end
end
end
end
else
SetupWeaponAttachments(ply, TEAM_SURV) -- Call the setup function if we can't find weapon table
end
end[/code]
My way of doing it is probably not the best either, but it should do the job.
[QUOTE=ThreeDog;49592151]I've implemented something like this in my own gamemode.
What I did is net.Broadcast when a player spawns, and give them a clientsidemodel weapon on every client, and set specific bones and positional and angular offsets in a table, that you can do yourself because it requires a bit of specific work. then I draw it with this function:
[code]function GM:PostPlayerDraw(ply)
if (ply == LocalPlayer():GetObserverTarget() and LocalPlayer():GetObserverMode() == OBS_MODE_IN_EYE) or
(ply == LocalPlayer() and !LocalPlayer():ShouldDrawLocalPlayer()) or
!ply:Alive() or !ply:Team() == TEAM_SURV then return end
if istable(ply.Weapons) then
for k, wep in pairs(ply:GetWeapons()) do
local slot = wep:GetSlot()
if slot and ply.Weapons[slot] then
for i=1,#ply.Weapons[slot] do
local wepData = ply.Weapons[slot][i]
if !(ply.Weapons[slot][i]:GetModel() ~= wep:GetModel() or (slot == 3 and wep.Ammo1 and wep:Ammo1() == 0) or wep == ply:GetActiveWeapon()) then
local pos, ang = Vector(), Angle()
if ply:LookupBone(wepData.bone) then pos, ang = ply:GetBonePosition(ply:LookupBone(wepData.bone)) end
pos = pos + (ang:Right() * wepData.pos.x)
pos = pos + (ang:Forward() * wepData.pos.y)
pos = pos + (ang:Up() * wepData.pos.z)
--Rotate bone angle with angle offsets. It must be in pitch, yaw, roll order.
ang:RotateAroundAxis(ang:Right(), wepData.ang.p)
ang:RotateAroundAxis(ang:Up(), wepData.ang.y)
ang:RotateAroundAxis(ang:Forward(), wepData.ang.r)
wepData:SetAngles(ang)
wepData:SetPos(pos)
wepData:SetRenderOrigin(pos)
wepData:SetRenderAngles(ang)
wepData:SetupBones()
wepData:DrawModel()
wepData:SetRenderOrigin()
wepData:SetRenderAngles()
wepData:SetModel(wep:GetModel() == "models/weapons/w_pist_elite.mdl" and "models/weapons/w_pist_elite_single.mdl" or wep:GetModel())
end
end
end
end
else
SetupWeaponAttachments(ply, TEAM_SURV) -- Call the setup function if we can't find weapon table
end
end[/code]
My way of doing it is probably not the best either, but it should do the job.[/QUOTE]
Are those checks at the start necessary? PostPlayerDraw isn't called unless you can see the world model, so if you're in first person it won't draw the models anyway.
So this is what I currently have
[lua]
function ChangeModelOnWeaponSwitch( ply, oldWeapon, newWeapon )
-- weapon_mu_magnum
if newWeapon:GetClass() == "weapon_mu_magnum" then
-- If the player has the magnum equip Hat and make sure the player is using the bystander model
ply:SetModel( bystander_model )
ply:PS_GiveItem( gun_model )
ply:PS_EquipItem( gun_model )
ply:PS_HolsterItem( knife_model )
end
-- weapon_rp_hands
if newWeapon:GetClass() == "weapon_rp_hands" then
-- If the player has hands equipped holster the Hat and make sure the player is using the bystander model
ply:SetModel( bystander_model )
ply:PS_HolsterItem( gun_model )
ply:PS_HolsterItem( knife_model )
table.remove(murderTable, 1)
--print(table.Count(murderTable), newWeapon:GetClass())
end
end
hook.Add( "PreDrawHalos", "AddHalos", function()
halo.Add( murderTable, Color( 255, 0, 0), 5, 5, 5, true, false )
end )
hook.Add( "PlayerSwitchWeapon", "ChangeModelOnWeaponSwitch_event", ChangeModelOnWeaponSwitch)
[/lua]
A little confused by your code and how It would be done, never really done client side model manipulation before. Is there anyway to change this code within if newWeapon:GetClass() == "weapon_mu_magnum" then I also need some way of removing the model when they switch back.
Also here is pos = pos + (ang:Up() * -40) + (ang:Forward() * -10) in the pointshop item lua
Anyone with more experience then me in this got any ideas? I'm sure the answer is in the code that ThreeDog listed above but I have no idea on how to use it. The lua file listed about runs in the the gamemodes folder but i'm not sure if this needs to be run client side.
This is how I did it. This code won't work right off the bat, this is just an example of how you can do it.
[lua]
function ITEM:CreateHat( )
self.Hat = ClientsideModel( self.Model , RENDERGROUP_OPAQUE )
self.Hat:SetNoDraw( true )
local index = 1
if ( self.Offset[self.Player:GetModel()] ) then index = self.Player:GetModel() end
self.Hat:SetModelScale( self.Offset[index].Scale, 0 )
end
function ITEM:OnEquip( _Player )
self.Equiped = true
self.Player = _Player
if not self.Hat and CLIENT then
self:CreateHat()
end
end
function ITEM:OnHolister( _Player )
self.Equiped = false
self.Player = false
if self.Hat and CLIENT then
SafeRemoveEntity( self.Hat )
end
end
function ITEM:CalculateOffset( pos, ang )
local index = 1
if ( self.Offset[self.Player:GetModel()] ) then index = self.Player:GetModel() end
local Voffset = Vector( self.Offset[index].Vector.x, self.Offset[index].Vector.y, self.Offset[index].Vector.z) * ( self.Player:GetModelScale() or 1 );
Voffset:Rotate( ang )
ang:RotateAroundAxis(ang:Right(), self.Offset[index].Angle.r); --Rotate around the axis (to the right) -90 degree's
ang:RotateAroundAxis(ang:Up(), self.Offset[index].Angle.p); --Rotate around the axis (upwards) 90
ang:RotateAroundAxis(ang:Forward(), self.Offset[index].Angle.y);
pos = pos + Voffset
return pos, ang
end
function ITEM:PostDrawOpaqueRenderables( )
if not self.Player or not self.Equiped then return end
if self.Player == LocalPlayer() and not self.Player:ShouldDrawLocalPlayer() then return end
local Ent = self.Player
if not self.Player:Alive() then Ent = self.Player:GetRagdollEntity() end
if (IsValid(Ent) and hook.Call( "InventoryShouldDrawHats", GAMEMODE, self.Player )) then
local pos, ang = self:CalculateOffset( Ent:GetBonePosition( self.BoneIndex ) )
local index = 1
if ( self.Offset[self.Player:GetModel()] ) then index = self.Player:GetModel() end
self.Hat:SetPos( pos )
self.Hat:SetAngles( ang )
self.Hat:SetModelScale( self.Offset[index].Scale, 0 )
self.Hat:DrawModel( )
end
end
[/lua]
This is just copy and pasted to where I think It should go, am I in the right ball park?
[lua]
function ITEM:CreateHat( )
self.Hat = ClientsideModel( "models/placeofmodel" , RENDERGROUP_OPAQUE )
self.Hat:SetNoDraw( true )
local index = 1
if ( self.Offset[self.Player:GetModel()] ) then index = self.Player:GetModel() end
self.Hat:SetModelScale( self.Offset[index].Scale, 0 )
end
function ChangeModelOnWeaponSwitch( ply, oldWeapon, newWeapon, _Player )
-- weapon_mu_magnum
if newWeapon:GetClass() == "weapon_mu_magnum" then
-- If the player has the magnum equip Hat and make sure the player is using the bystander model
ply:SetModel( bystander_model )
self.Equiped = true
self.Player = _Player
if not self.Hat and CLIENT then
self:CreateHat()
end
end
-- weapon_rp_hands
if newWeapon:GetClass() == "weapon_rp_hands" then
-- If the player has hands equipped holster the Hat and make sure the player is using the bystander model
ply:SetModel( bystander_model )
table.remove(murderTable, 1)
--print(table.Count(murderTable), newWeapon:GetClass())
self.Equiped = false
self.Player = false
if self.Hat and CLIENT then
SafeRemoveEntity( self.Hat )
end
end
end
hook.Add( "PreDrawHalos", "AddHalos", function()
halo.Add( murderTable, Color( 255, 0, 0), 5, 5, 5, true, false )
end )
hook.Add( "PlayerSwitchWeapon", "ChangeModelOnWeaponSwitch_event", ChangeModelOnWeaponSwitch)
function ITEM:CalculateOffset( pos, ang )
local index = 1
if ( self.Offset[self.Player:GetModel()] ) then index = self.Player:GetModel() end
local Voffset = Vector( self.Offset[index].Vector.x, self.Offset[index].Vector.y, self.Offset[index].Vector.z) * ( self.Player:GetModelScale() or 1 );
Voffset:Rotate( ang )
ang:RotateAroundAxis(ang:Right(), self.Offset[index].Angle.r); --Rotate around the axis (to the right) -90 degree's
ang:RotateAroundAxis(ang:Up(), self.Offset[index].Angle.p); --Rotate around the axis (upwards) 90
ang:RotateAroundAxis(ang:Forward(), self.Offset[index].Angle.y);
pos = pos + (ang:Up() * -40) + (ang:Forward() * -10)
return pos, ang
end
function ITEM:PostDrawOpaqueRenderables( )
if not self.Player or not self.Equiped then return end
if self.Player == LocalPlayer() and not self.Player:ShouldDrawLocalPlayer() then return end
local Ent = self.Player
if not self.Player:Alive() then Ent = self.Player:GetRagdollEntity() end
if (IsValid(Ent) and hook.Call( "InventoryShouldDrawHats", GAMEMODE, self.Player )) then
local pos, ang = self:CalculateOffset( Ent:GetBonePosition( self.BoneIndex ) )
local index = 1
if ( self.Offset[self.Player:GetModel()] ) then index = self.Player:GetModel() end
self.Hat:SetPos( pos )
self.Hat:SetAngles( ang )
self.Hat:SetModelScale( self.Offset[index].Scale, 0 )
self.Hat:DrawModel( )
end
end
[/lua]
[QUOTE=James xX;49597278]This code won't work right off the bat, [B]this is just an example of how you can do it.[/B]
[/QUOTE]
[QUOTE=James xX;49597452][/QUOTE]
Right I know, I am just asking would this be the proper placement within the code? Like do you see anything wrong that would be a major issue? Am I on the right path?
[QUOTE=Ztiep;49597466]Right I know, I am just asking would this be the proper placement within the code? Like do you see anything wrong that would be a major issue? Am I on the right path?[/QUOTE]
For a short list:
- ITEM is undefined, because the code I gave you was just an example
- murderTable is undefined.
- self.Offset in ITEM:CalculateOffset( ) is undefined
- self.Player in ITEM:PostDrawOpaqueRenderables( ) is undefined
- the hook "InventoryShouldDrawHats" is undefined and therefore will return nil, therefore will not run the if statement in ITEM:PostDrawOpaqueRenderables( )
- ITEM:PostDrawOpaqueRenderables( ) isn't hooked to anything
- self.BoneIndex in ITEM:PostDrawOpaqueRenderables( ) is undefined
- self.Hat in ITEM:PostDrawOpaqueRenderables( ) is undefined because ITEM:CreateHat( ) is never called
So I would say no, it isn't the proper placement in the code because all you did was copy and paste it without trying to understand what it does, and inevitably didn't understand what to do with it.
the variable self.Hat should be a ClientsideModel, and is drawn in the hook PostDrawOpaqueRenderables. In this, the position of the hat is calculated by ITEM:CalculateOffset( ). This takes the angle and position of the bone the hat is following, and adds an offset to it (because eat hat will fit each model differently). Then, the ClientsideModel is drawn.
In short: ClientsideModel gets drawn at the right offset of a bone on the player in PostDrawOpaqueRenderables.
Sorry, you need to Log In to post a reply to this thread.