Raised This Month: $51 Target: $400
 12% 

A quick look?


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Nimgoble
Junior Member
Join Date: Apr 2006
Old 08-30-2008 , 10:44   A quick look?
Reply With Quote #1

Hello again. I was wondering if anyone would take a quick look at a couple of pieces of code of mine and tell me if they see anything wrong. There is something in this code that is crashing the server after about 20 minutes or so. It could be random, though I don't think it is. It always happens when the crossbow is being fired.

Code:
void ss_player::AdjustCrossbowFireRate()
{
	META_LOG(g_PLAPI, "Player %i Adjusting Crossbow Fire Rate", ss_index );

	if( playerinfomanager != NULL && pPlayer != NULL )
	{
		float time = playerinfomanager->GetGlobalVars()->curtime;

		//AMMO_OFFSET is an array that goes from 1576 to 1704.  The difference is 128.
		//The upper bounds of the ammo array is MAX_AMMO, which is 32. 128 / 32 = 4
		//The size of each ammo counter is 4 bytes.  So the ammo array is:
		//0:					1576 - 1579
		//AMMO_AR2:				1580 - 1583
		//AMMO_AR2_ALT:			1584 - 1587
		//AMMO_PISTOL:			1588 - 1591
		//AMMO_SMG1:			1592 - 1595
		//AMMO_357:				1596 - 1599
		//AMMO_CROSSBOW:		1600 - 1603
		//AMMO_SHOTGUN:			1604 - 1607
		//AMMO_RPG:				1608 - 1611
		//AAMMO_SMG1GREN:		1612 - 1615
		//AMMO_FRAG:			1616 - 1619
		//AMMO_SLAM:			1620 - 1623
		//So, my original calculation: AMMO_OFFSET + (AMMOO_CROSSBOW * ) = 
		//1576 + (6 * 4) = 1576 + 24 = 1600, which is the crossbow.  Shit.  I WAS correct...So why is it crashing?

		datamap_t *pMap = pPlayer->GetDataDescMap();
		int AMMO_OFFSET = GetOffset( pMap, "m_iAmmo" );

		
		if( AMMO_OFFSET > 0 )
		{
			//Is this right?  Setting the crossbow ammo pointer to one less....memory address?
			*(int *)((char *)pPlayer + (AMMO_OFFSET + (AMMO_CROSSBOW * 4 ))) = *(int *)((char * )pPlayer + (AMMO_OFFSET + (AMMO_CROSSBOW * 4 ))) - 1;
		}
		UpdateCrossbow();
	}
}
The part where I set the ammo is my guess on what's going wrong. I don't know if that's the correct way to do it.

Here is the UpdateCrossbow and UpdateActiveWeapon, just in case.

Code:
void ss_player::UpdateCrossbow()
{
	META_LOG(g_PLAPI, "Player %i Begin Update Crossbow", ss_index );

	//Make sure we have the crossbow.
	if( pCrossbow )
	{
		//time.  Used to set the next fire time of the player and crossbow
		float time = 0;

		//Make sure playerinfomanager isn't null.
		if( playerinfomanager != NULL )
			playerinfomanager->GetGlobalVars()->curtime + ss_crossbow_refire.GetFloat();
		else
			return;
		
		//Our data maps.  Used to find the offsets of data members
		datamap_t *pPlayerMap, *pCrossbowMap, *pCombatCharMap;

		//Continuing without these would be pointless and stupid.
		if( pPlayer == NULL ||
			pCrossbow == NULL ||
			pCombatChar == NULL )
			return;

		pPlayerMap = pPlayer->GetDataDescMap();
		pCrossbowMap = pCrossbow->GetDataDescMap();
		pCombatCharMap = pCombatChar->GetDataDescMap();

		//Don't mess with anything if we don't have ALL of our datamaps.
		if( pPlayerMap == NULL ||
			pCrossbowMap == NULL ||
			pCombatCharMap == NULL )
			return;

		//The individual data member offsets.
		int AMMO_OFFSET, CLIP1_OFFSET, IDLE_TIME_OFFSET, NEXT_PRIMARY_ATTACK_OFFSET, NEXT_ATTACK_OFFSET, IN_RELOAD_OFFSET;

		//Player
		AMMO_OFFSET = GetOffset( pPlayerMap, "m_iAmmo" );

		//Crossbow
		CLIP1_OFFSET = GetOffset( pCrossbowMap, "m_iClip1" ); 
		IDLE_TIME_OFFSET = GetOffset( pCrossbowMap, "m_flTimeWeaponIdle" );
		NEXT_PRIMARY_ATTACK_OFFSET = GetOffset( pCrossbowMap, "m_flNextPrimaryAttack" );
		IN_RELOAD_OFFSET = GetOffset( pCrossbowMap, "m_bInReload" );

		//CombatChar
		NEXT_ATTACK_OFFSET = GetOffset( pCombatCharMap, "m_flNextAttack" );

		//Don't give more ammo when we run out.
		if( *(int *)((char * )pPlayer + (AMMO_OFFSET + (AMMO_CROSSBOW * 4 ))) <= 0 )
		{
			META_LOG(g_PLAPI, "End UpdateCrossbow() with no ammo. player: %i", ss_index);
			return;
		}

		//RELOAD.  FAST
		if( *(int *)((char*)pCrossbow + CLIP1_OFFSET) <= 0 )
		{
			*(int *)((char*)pCrossbow + CLIP1_OFFSET) = 1;
		}
		//IDLE TIME = time
		*(float *)((char *)pCrossbow + IDLE_TIME_OFFSET) = time;
		//NEXT ATTACK TIME = NOW
		*(float *)((char *)pCrossbow + NEXT_PRIMARY_ATTACK_OFFSET) = time;

		//NEXT PLAYER ATTACK TIME = NOW
		if( pCombatChar != NULL )
			*(float *)((char *)pCombatChar + NEXT_ATTACK_OFFSET) = time;

		//Don't need a reload.
		*(bool *)((char *)pCrossbow + IN_RELOAD_OFFSET) = false;
	}
	META_LOG(g_PLAPI, "Player %i End Update Crossbow", ss_index );
}
Too make sure that nothing was going wrong in there, I went back and checked to see if everything was instantiated. I think I dotted every "i" and crossed every "t", but sometimes you miss things like that.

Here is the ActiveWeapon code.

Code:
void ss_player::UpdateActiveWeapon()
{
	META_LOG(g_PLAPI, "Player %i Begin Active Weapon Update", ss_index );
	datamap_t *pCombatCharMap = NULL;
	int ACTIVE_OFFSET = 0;
	CBaseHandle *pHandle = NULL;

	if( pCombatChar != NULL )
	{
		pCombatCharMap = pCombatChar->GetDataDescMap();
		if( pCombatCharMap != NULL )
		{
			ACTIVE_OFFSET = GetOffset( pCombatCharMap, "m_hActiveWeapon" );
			pHandle = (CBaseHandle *)((char *)pCombatChar + ACTIVE_OFFSET);
		}
	}

	if( pHandle != NULL && m_Engine != NULL )
	{
		edict_t *pEdict = m_Engine->PEntityOfEntIndex(pHandle->GetEntryIndex());
		if( pEdict != NULL )
		{
			CBaseEntity *pEnt = pEdict->GetIServerEntity()->GetBaseEntity();
			if( pEnt  != NULL )
			{
				pActive = (CBaseCombatWeapon*)pEnt;
				if( pActive != NULL)
				{
					/* If our active weapon is not equal to our shotgun pointer: unhook the shotgun.
						we don't need it hooked if it isn't active.  Then check to see if our active weapon IS
						a shotgun.  If so, hook it.
					*/
					if( pActive != pShotgun )
					{
						if(pShotgun != NULL )
						{
							UnHookShotgun();
						}
						
						if( (stricmp(pActive->GetClassname(), "weapon_shotgun") == 0 ) )
						{	
							pShotgun = pActive;
							HookShotgun();
						}
					}
					if( pActive != pCrossbow )
					{
						if( pCrossbow != NULL )
						{
							UnHookCrossbow();
						}
						
						if( (stricmp(pActive->GetClassname(), "weapon_crossbow") == 0) )
						{
							pCrossbow = pActive;
							if( pCombatChar != NULL )
							{
								datamap_t *pMap = pCombatChar->GetDataDescMap();
								if( pMap != NULL )
								{
									int AMMO_OFFSET = GetOffset( pMap, "m_iAmmo" );
									//We have a new crossbow, time to fill up the ammo.
									*(int *)((char *)pCombatChar + (AMMO_OFFSET + (AMMO_CROSSBOW * 4))) = ss_crossbow_ammo.GetInt();

								}
							}
							HookCrossbow();
						}
					}
				}
			}
		}
	}
	META_LOG(g_PLAPI, "Player %i End Active Weapon Update", ss_index );
}
The above code checks the current weapon and hooks it if necessary.

I've been banging my head against the keyboard for weeks trying to figure this out. I appreciate the help.
Nimgoble is offline
Nimgoble
Junior Member
Join Date: Apr 2006
Old 08-31-2008 , 00:16   Re: A quick look?
Reply With Quote #2

Oye... 17 views. Bailopan was most likely one of them, and I think he was my best shot at an answer. Damn...
Nimgoble is offline
PM
hello, i am pm
Join Date: Jan 2004
Location: Canalization
Old 09-05-2008 , 06:43   Re: A quick look?
Reply With Quote #3

I didn't see anything apparently wrong at the first glance. Do backtraces or function enter/leave logs give any hints?
__________________
hello, i am pm
PM is offline
Keeper
Senior Member
Join Date: Nov 2006
Old 09-05-2008 , 08:44   Re: A quick look?
Reply With Quote #4

Does the crossbow fire before the crash? As in, does the animation sequence begin?

Make sure to check your dump file to see if it is something in your code. Most likely you're doing something the engine isn't liking, so you'll probably get the disassembly screen.

Does it work for that 20 minutes like you intend it to? And as PM said, what part is it crashing in ( from the META_LOG output... )

EDIT:

What are you trying to do here in UpdateCrossbow?
Code:
if( playerinfomanager != NULL )
            playerinfomanager->GetGlobalVars()->curtime + ss_crossbow_refire.GetFloat();
I know there's a bug in HL2DM that causes problems with the crossbow not firing when you expect it to. It's related to the animation sequences and the timing. Could it be that you are changing one of the offsets during an animation cycle? i.e. IN_RELOAD_OFFSET ?

Last edited by Keeper; 09-05-2008 at 08:57.
Keeper is offline
Nimgoble
Junior Member
Join Date: Apr 2006
Old 09-07-2008 , 00:32   Re: A quick look?
Reply With Quote #5

Hey guys, thanks for the answers.

@PM: No, they don't, which is really weird. They aren't even called, but I know it's in the functions because they are working...

@Keeper: Haven't messed with the dump files yet. And yes, it runs fine for the 20 minutes. I can't believe I missed that playerinfomanager thing. I meant to set time = curtime + crossbow_refire. Instead, I was just adding those two and not doing anything with them. And I'm changing the offsets IMMEDIATELY after the crossbow fires. I change the m_bNeedsReload to false so it skips the animations completely. I went back and fixed that line you pointed out. Hopefully that does SOMETHING.
Nimgoble is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 12:19.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode