ODE Middleware

But it is almost exactly the same ( at least the necessary parts )

from pandac.PandaModules import Point3, Vec3
from direct.interval.IntervalGlobal import *
from direct.showbase.DirectObject import DirectObject

from odeWorldManager import *
from pickables import PickableObject

import random
import configurations


class Firearm(PickableObject, DirectObject):
	def __init__(self, name="handgun", weight=0.630):
		PickableObject.__init__(self, name, weight)
		
		self.config = configurations.Configuration()
		
		
		
		self.pickableType = "firearm"
		
		
		self.modelPath = "models/p90.egg"
		self.worldModelPath = "models/p90.egg"
		self.hudModelPath   = "models/p90.egg"
		self.geomSize = (0.054, 0.381, 0.227)
		
		"""
		Is it automatic or semi-automatic?
		"""
		self.automatic = False
		
		"""
		How far do you want the bullets to go?
		"""
		self.effectiveRange = 300.0
		
		"""
		Rate of Fire for automatic weapons.
		"""
		self.autoROF = 250.0
		
		"""
		Used for ROF, more on that in the update method.
		"""
		self.autoAccumulator = 0.0
		
		"""
		Number of rays to search for hits with. This basically
		translates to this: If it's more than one, you have a shotgun.
		It it's one -- a pistol or a rifle.
		"""
		self.aimRaysNum = 1
		
		"""
		Holds aim rays.
		"""
		self.aimRays = []
		
		"""
		If you have more than one aim ray, then here you can set how
		dispersed they're going to be.
		"""
		self.shotgunDispersion = 0.2
		
		"""
		Are we shooting ATM?
		"""
		self.shooting = False
		
		"""
		Contains the hits.
		"""
		self.aimCollisions = []
		
		
	
	"""
	The callback for aim ray collisions.
	"""
	def aimCollision(self, entry, object1, object2):
		"""
		No point hitting triggers or ccd helpers.
		"""
		if object2.objectType is ["ccd"]:
			return
		
		"""
		So we don't shoot ourselves.
		"""
		if object2 is self.owner:
			return
		
		"""
		Append the hit to the list.
		"""
		self.aimCollisions.append([entry, object2])
	
	def destroy(self):
		for ray in self.aimRays:
			self.map.worldManager.removeObject(ray)
			ray.destroy()
		del self.aimCollisions
		del self.aimRays
		pickableObject.destroy(self)
		self.ignoreAll()
	
	"""
	Create the requested number of aim rays.
	"""
	def createAimRays(self):
		for i in range(self.aimRaysNum):
			self.createAimRay()
	
	"""
	Create a single aim ray.
	"""
	def createAimRay(self):
		ray = rayObject(self.map)
		ray.objectType = "ray"
		ray.setRayGeom(self.effectiveRange, [Vec3(0,0,0), Vec3(0,0,-1)])
		ray.collisionCallback = self.aimCollision
		
		self.map.worldManager.addObject(ray)
		self.aimRays.append(ray)
	
	def destroyAimRays(self):
		for ray in self.aimRays:
			self.map.worldManager.removeObject(ray)
			ray.destroy()
		self.aimRays = []
		self.aimCollisions = []
	
	def selectionCallback(self, character, direction):
		PickableObject.selectionCallback(self, character, direction)
		
		"""
		Create the rays when we pick up the gun. No need having them around all the time.
		
		NOTE: In my game, I actually create the rays when the Player withdraws the gun
		from the inventory, but the actual usage depends on application's design.
		"""
		self.createAimRays()
	
	def drop(self):
		"""
		Destroy the rays when we drop the gun.
		"""
		self.destroyAimRays()
		PickableObject.drop(self)
	
	def useHeld(self):
		"""
		Start shooting...
		"""
		self.shooting = True
		return True
	
	def useHeldStop(self):
		"""
		Stop shooting an automatic weapon.
		Semi automatic weapons stop shooting by themselves, right after
		one update pass.
		"""
		if self.automatic:
			self.stopShooting()
		return
	
	def shoot(self, dir):
		"""
		Process the collected hits.
		"""
		for entry, object in self.aimCollisions:
			p = entry.getContactPoint(0)
			if object.body:
				object.body.enable()
				object.body.addForceAtPos(dir*(10**2), p)
	
	def stopShooting(self):
		"""
		Stop shooting and clear the collisions accumulator.
		"""
		self.shooting = False
		self.autoAccumulator = 0.0
		
	def update(self, stepSize):
		PickableObject.update(self,stepSize)
		
		if not self.aimRays:
			self.aimCollisions = []
			return
		
		"""
		Only process hits if the gun is picked up.
		"""
		if self.owner:
			"""
			Get the desired position and direction of the aim ray/s.
			
			NOTE that currently there's only support for Player (camera)
			and not NPCs. Supports for NPCs will come in the next major version.
			"""
			pos = base.cam.getPos(render) + render.getRelativeVector(base.cam, Vec3(0, 0.8, 0))
			dir = render.getRelativeVector(base.cam, Vec3(0, 1.0, 0))
			
			"""
			Handle the Rays and add some random dispersion.
			"""

			for ray in self.aimRays:
				"""
				Scatter the rays within the limits set by the shotgunDispersion variable.
				"""
				x = random.uniform(-self.shotgunDispersion, self.shotgunDispersion)
				z = random.uniform(-self.shotgunDispersion, self.shotgunDispersion)
				
				"""
				Tweak the direction to take the random values into account.
				"""
				rayDir = Vec3(dir)
				rayDir[0] += x
				rayDir[2] += z
				
				"""
				Position the ray.
				"""
				ray.geom.set(pos, rayDir)
			
			"""
			Handle automatic weapons.
			"""
			if self.automatic and self.shooting:
				"""
				If this is the first frame we're self.shooting == True,
				shoot once and then continue processing.
				"""
				if self.autoAccumulator == 0.0:
					self.shoot(dir)
				
				"""
				Add the rate-of-fire to the accumulator.
				"""
				self.autoAccumulator += self.autoROF
				
				"""
				Get the ROF per second
				"""
				currentROF = 1.0/self.autoAccumulator
				
				"""
				Call shoot method as many times as shots fitting in the
				simulation time step.
				
				That's what the accumulator is for -- thanx to that,
				the speed of shooting depends on values set, not on
				the simulation's update rate.
				"""
				if currentROF < stepSize:
					for i in range(int(stepSize / currentROF)):
						self.shoot(dir)
					self.autoAccumulator = 0.0
			
				"""
				Handle semi automatic shooting.
				"""
			elif self.shooting:
				self.shoot(dir)
		
		"""
		If semi-automatic, make sure to shoot only once.
		"""
		if not self.automatic:
			self.stopShooting()
		
		"""
		Clear aim collisions before the next frame.
		"""
		self.aimCollisions = []
		
	def loadConfig(self, filename):
		self.config.addConfig(filename)
		self.configName = self.config.configs.keys()[0]
		
		self.activateConfigs()
		
	def activateConfigs(self):
		self.name   = self.config.getConfig(self.configName)["properties"]["name"]
		self.rps    = self.config.getConfig(self.configName)["properties"]["rps"]
		self.type   = self.config.getConfig(self.configName)["properties"]["type"]
		self.hudModelPath  = self.config.getConfig(self.configName)["properties"]["model"]
		self.worldModelPath  = self.config.getConfig(self.configName)["properties"]["worldmodel"]

		self.modelPath = self.worldModelPath

That’s the firearm module

I’ve renamed pickableObject to PickableObject because I am used to have classes capitalized :wink: I’ve capitalized all classes =)

I hope you can find my mistake

Thank you very much
blenderkid