[C-Strike:Source] Change Weapon Model

Please post any questions about developing your plugin here. Please use the search function before posting!
RegWin32
Junior Member
Posts: 5
Joined: Sun Sep 29, 2019 6:12 pm

[C-Strike:Source] Change Weapon Model

Postby RegWin32 » Sun Sep 29, 2019 6:20 pm

Syntax: Select all

from engines.precache import Model
from events import Event
from players import UserCmd
from players.constants import PlayerButtons, PlayerStates
from players.entity import Player
from weapons.entity import Weapon
from entities.entity import BaseEntity
from engines.precache import Model
from stringtables.downloads import Downloadables
import math
from mathlib import Vector
from messages import SayText2
#=============================================================
#DOWNLOADS
#=============================================================
downloadables = Downloadables()
downloadables.add_directory('models/weapons/ak47-beast')

downloadables.add_directory('materials/models/weapons/v_models/CF_ak47_BEAST')
downloadables.add_directory('materials/models/weapons/w_models/CF_ak47_BEAST')

models = Model("models/weapons/ak47-beast/w_rif_ak47.mdl")
#=============================================================
#FUNCTIONS
#=============================================================
def set_weapon_model(game_event):
player = Player.from_userid(game_event['userid'])
player.set_name('AK47 Beast Test')
weapon = player.get_active_weapon()
if weapon.weapon_name == 'weapon_ak47':
weapon.set_model(models)

#=============================================================
#EVENTS
#=============================================================
@Event('player_jump')
def on_player_jump(game_event):
set_weapon_model(game_event)


Hello, I'm new to SourcePython and testing it for a while. Currently I'm trying to change the model of the AK47 to a Skin.
I can change my character model to the AK47 Skin but not the weapon model.
How do I change the model of a weapon ? :embarrassed:
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [C-Strike:Source] Change Weapon Model

Postby VinciT » Mon Sep 30, 2019 1:55 am

Hi RegWin32, welcome to the community! Hope you're having fun with SP.

From what I can tell, you'll need to change two models. The firstperson model (viewmodel) and the thirdperson one (worldmodel).
You can change the viewmodel by getting the predicted_viewmodel of the player and changing the m_nModelIndex property.
And I think you can change the worldmodel by changing the m_iWorldModelIndex property on the weapon itself.

I haven't had time to fully flesh it out, but give this a shot:

Syntax: Select all

# ../weapon_model_test/weapon_model_test.py

# Source.Python
from engines.precache import Model
from entities.entity import Entity
from entities.helpers import index_from_pointer
from entities.hooks import EntityCondition, EntityPreHook
from filters.entities import BaseEntityIter
from players.dictionary import PlayerDictionary
from stringtables.downloads import Downloadables
from weapons.dictionary import WeaponDictionary


downloadables = Downloadables()
downloadables.add_directory('models/weapons/ak47-beast')
downloadables.add_directory('materials/models/weapons/v_models/cf_ak47-beast')
downloadables.add_directory('materials/models/weapons/w_models/cf_ak47-beast')


beast_viewmodel = Model('models/weapons/ak47-beast/v_rif_ak47.mdl')
beast_worldmodel = Model('models/weapons/ak47-beast/w_rif_ak47.mdl')


# Dictionary used for storing/caching Player instances.
player_instances = PlayerDictionary()
# Same as above, just for weapons.
weapon_instances = WeaponDictionary()


@EntityPreHook(EntityCondition.is_player, 'weapon_switch')
def weapon_switch_pre(stack_data):
# Get the Player instance.
player = player_instances[index_from_pointer(stack_data[0])]
# Get the Weapon instance.
weapon = weapon_instances[index_from_pointer(stack_data[1])]

# Don't go further if this isn't an AK.
if 'ak47' not in weapon.classname:
return

# Add a small delay (single frame) before changing the models.
# Without this, the model change won't go through.
player.delay(0, change_weapon_models, (player, weapon))


def change_weapon_models(player, weapon):
# This is where you change the 'worldmodel' of the weapon.
weapon.world_model_index = beast_worldmodel.index
weapon.model = beast_worldmodel
# Find the 'predicted_viewmodel' for this player.
viewmodel = get_predicted_viewmodel(player)
# And this is where you change the 'viewmodel' of the weapon.
viewmodel.model = beast_viewmodel


def get_predicted_viewmodel(player):
# Go through all 'predicted_viewmodel' entities.
for base_entity in BaseEntityIter('predicted_viewmodel'):
# Is this the 'predicted_viewmodel' that we're looking for?
if base_entity.owner_handle == player.inthandle:
# Apparently, each player has two viewmodels. The one we need to
# change has the 'm_nViewModelIndex' property set to 0.
if base_entity.get_network_property_short('m_nViewModelIndex') == 0:
# Return an Entity instance of the 'predicted_viewmodel' for
# the specified player.
return Entity(base_entity.index)
return None
Last edited by VinciT on Wed Oct 02, 2019 12:45 am, edited 2 times in total.
ImageImageImageImageImage
RegWin32
Junior Member
Posts: 5
Joined: Sun Sep 29, 2019 6:12 pm

Re: [C-Strike:Source] Change Weapon Model

Postby RegWin32 » Mon Sep 30, 2019 7:45 am

Hi, first of all thanks for the quick response !
Your script works well, it does change the view and world models.
Somehow the script changes the weapon from right handed to left handed and flickers back to the old AK47 model.

I’ll test some things and edit this post later.
Thank you again, learned a lot by your well commented code.

Edit

Syntax: Select all

@EntityPreHook(EntityCondition.is_player, 'weapon_switch')
def weapon_switch_pre(stack_data):
player = player_instances[index_from_pointer(stack_data[0])]
weapon = weapon_instances[index_from_pointer(stack_data[1])]
if weapon.weapon_name != 'weapon_ak47' :
return
player.delay(0, change_weapon_models, (player, weapon))
weapon.set_model(beast_worldmodel) #The worldmodel ODDLY stopped the flickerring


The weapon still is opposite handed, i don't really know why.
lefthanded = AK on right.
righthanded = AK on left.
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [C-Strike:Source] Change Weapon Model

Postby VinciT » Mon Sep 30, 2019 10:28 pm

RegWin32 wrote:Thank you again, learned a lot by your well commented code.
No problem! Glad I could help.

RegWin32 wrote:The weapon still is opposite handed, i don't really know why.
That's pretty odd, on my end the AK is showing up correctly:

Maybe we have different models? I got the model from cs-fs.ru.
RegWin32
Junior Member
Posts: 5
Joined: Sun Sep 29, 2019 6:12 pm

Re: [C-Strike:Source] Change Weapon Model

Postby RegWin32 » Tue Oct 01, 2019 6:32 am

Hi,
The model is broken Iam using.
Thanks for linking me yours, your model works like a charm, do you know the reason why “hard” setting the weapon model fixed the flickering ?
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [C-Strike:Source] Change Weapon Model

Postby L'In20Cible » Tue Oct 01, 2019 8:02 am

VinciT wrote:

Syntax: Select all

# This is where you change the 'worldmodel' of the weapon.
weapon.set_property_short('m_iWorldModelIndex', beast_worldmodel.index)

Could be:

Syntax: Select all

weapon.world_model_index = beast_worldmodel.index


VinciT wrote:

Syntax: Select all

# And this is where you change the 'viewmodel' of the weapon.
viewmodel.set_datamap_property_short('m_nModelIndex', beast_viewmodel.index)

Could be:

Syntax: Select all

viewmodel.model_index = beast_viewmodel.index

Or more preferably:

Syntax: Select all

viewmodel.model = beast_viewmodel

Because the model property is setting both; the name and the index: Entity.set_model. The name not being set is probably what was causing the issue referenced in that post:

RegWin32 wrote:Thanks for linking me yours, your model works like a charm, do you know the reason why “hard” setting the weapon model fixed the flickering ?

Because client predictions in the source engine always been different from a client to another (due to drivers, dx version, predicted latency calculations, etc.) especially if you are testing on a local server, and he is not, etc. I also remember that back in the ES days, the view model had to be set every frame to ensure all clients do not attempt to revert it from a frame to another. Something else that is most likely in cause, is the fact that you used set_datamap_property_short instead of set_property_short/set_network_property_short. Remember the former is only setting the value server-side, while the laters also mark the edict has changed (if the prop is networked, which the model index is) which force it to be networked again: Entity._set_property.
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [C-Strike:Source] Change Weapon Model

Postby VinciT » Tue Oct 01, 2019 11:38 pm

Thanks for the pointers, L'In20Cible. I've updated the code in my post.
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Re: [C-Strike:Source] Change Weapon Model

Postby satoon101 » Wed Oct 02, 2019 12:00 am

I don't think your get_predicted_viewmodel will work the way you're intending. It will currently return the last predicted_viewmodel entity every time. You should either break or return once you have found the correct one:

Syntax: Select all

def get_predicted_viewmodel(player):
# Go through all 'predicted_viewmodel' entities.
for base_entity in BaseEntityIter('predicted_viewmodel'):
# Is this the 'predicted_viewmodel' that we're looking for?
if base_entity.owner_handle == player.inthandle:
# Return an Entity instance of the 'predicted_viewmodel' for the specified player.
return Entity(base_entity.index)
return None


To illustrate my point:

Syntax: Select all

x = 4
for i in range(7):
if i != x:
continue
print(i)

# vs
x = 4
for i in range(7):
if i == x:
break
print(i)
Image
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [C-Strike:Source] Change Weapon Model

Postby VinciT » Wed Oct 02, 2019 12:46 am

Jesus.. You're right. The funny thing is, that's how I had it at first. But then I switched to the incorrect one, cause I was getting really strange results (double/mirrored viewmodels).
And now I know why. The player has two viewmodels, and setting the one that has the m_nViewModelIndex property set to 1 creates the mirrored viewmodel.

I've fixed this rookie mistake in the post above :tongue:.
ImageImageImageImageImage
RegWin32
Junior Member
Posts: 5
Joined: Sun Sep 29, 2019 6:12 pm

Re: [C-Strike:Source] Change Weapon Model

Postby RegWin32 » Wed Oct 02, 2019 8:28 am

Hey, thanks for all the helpful comments.
After applying the changes of VinciT.
You said the m_nViewModelIndex property needs to be 0.
And as you did, I question it and only continue on a 0, still after firing a few bullets (one round max.) the AK47 model will mirror meaning, revert back to the old model on the oppsite hand.

Syntax: Select all

@EntityPreHook(EntityCondition.is_player, 'weapon_switch')
def weapon_switch_pre(stack_data):
player = player_instances[index_from_pointer(stack_data[0])]
weapon = weapon_instances[index_from_pointer(stack_data[1])]
if weapon.weapon_name == 'weapon_ak47':
player.delay(0, change_weapon_models, (player, weapon, ak47_beast_worldmodel,ak47_beast_viewmodel))
elif weapon.weapon_name == 'weapon_knife':
pass
elif weapon.weapon_name == 'weapon_ump45' :
player.delay(0, change_weapon_models,(player, weapon, thompson_worldmodel,thompson_viewmodel))
else :
SayText2(str(weapon.weapon_name)).send()

def change_weapon_models(player, weapon, worldModel:Model, viewModel:Model):
weapon.world_model_index = worldModel.index
weapon.model = worldModel
viewmodel = get_predicted_viewmodel(player)
viewmodel.model = viewModel


def get_predicted_viewmodel(player):
# Go through all 'predicted_viewmodel' entities.
for base_entity in BaseEntityIter('predicted_viewmodel'):
# Is this the 'predicted_viewmodel' that we're looking for?
if base_entity.owner_handle == player.inthandle:
if base_entity.get_network_property_short('m_nViewModelIndex') == 0:
# Return an Entity instance of the 'predicted_viewmodel' for the specified player.
return Entity(base_entity.index)
return None
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [C-Strike:Source] Change Weapon Model

Postby L'In20Cible » Wed Oct 02, 2019 8:56 am

RegWin32 wrote:And as you did, I question it and only continue on a 0, still after firing a few bullets (one round max.) the AK47 model will mirror meaning, revert back to the old model on the oppsite hand.

Test after typing the following in your client console:

Code: Select all

cl_predictweapons 0


If the issue goes away, then this is caused by the prediction and you will need to apply the model every frame as stated above.
RegWin32
Junior Member
Posts: 5
Joined: Sun Sep 29, 2019 6:12 pm

Re: [C-Strike:Source] Change Weapon Model

Postby RegWin32 » Wed Oct 02, 2019 2:00 pm

L'In20Cible wrote:
RegWin32 wrote:And as you did, I question it and only continue on a 0, still after firing a few bullets (one round max.) the AK47 model will mirror meaning, revert back to the old model on the oppsite hand.

Test after typing the following in your client console:

Code: Select all

cl_predictweapons 0


If the issue goes away, then this is caused by the prediction and you will need to apply the model every frame as stated above.


I got it to work.

Code: Select all

cl_predictweapons 0
did nothing at all.

Syntax: Select all

viewmodel.model = viewModel
did nothing at all

Syntax: Select all

def change_weapon_models(player, weapon, worldModel: Model, viewModel: Model):
weapon.world_model_index = worldModel.index
weapon.model = worldModel
viewmodel = get_predicted_viewmodel(player)
viewmodel.model_index = viewModel.index

def get_predicted_viewmodel(player):
for base_entity in BaseEntityIter('predicted_viewmodel'):
if base_entity.owner_handle == player.inthandle:
if base_entity.get_network_property_short('m_nViewModelIndex') == 0:
return base_entity


This fixed the behavior, the weapon animation is slightly off, but that's ok for now.

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 24 guests