Teancum Posted April 22, 2016 Share Posted April 22, 2016 I'm trying to program the multiple barrel shots of the Fusion Cutter through code. I have a CASE statement that lets me loop through four firing sections representing four barrels -- that works correctly. The problem is when I try to create an offset vector and add them together for each barrel it crashes. I'm not very good with vectors admittedly. The offending code is commented half way down. The offending code: vec3_t start; int damage = weaponData[WP_DEMP2].damage; int currentbarrel = NULL; gentity_t *missile; vec3_t offset; vec3_t barrelUno; vec3_t barrelDos; vec3_t barrelTres; vec3_t barrelQuatro; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall WP_MissileTargetHint(ent, start, forwardVec); /*missile = CreateMissile(start, forwardVec, DEMP2_VELOCITY, 10000, ent);*/ switch (currentbarrel) { case 1: //leftmost barrel /*offset[0] = -2.0; offset[1] = 0.0; offset[2] = 0.0; VectorAdd(start, offset, barrelUno);*/ missile = CreateMissile(barrelUno, forwardVec, DEMP2_VELOCITY, 10000, ent); break; case 2: //left-mid barrel missile = CreateMissile(start, forwardVec, DEMP2_VELOCITY, 10000, ent); break; case 3: //right-mid barrel missile = CreateMissile(start, forwardVec, DEMP2_VELOCITY, 10000, ent); break; case 4: //rightmost barrel missile = CreateMissile(start, forwardVec, DEMP2_VELOCITY, 10000, ent); break; default: //catch all, also during initialization //set to 1, but fire from barrel 4 currentbarrel = 1; missile = CreateMissile(start, forwardVec, DEMP2_VELOCITY, 10000, ent); } Link to comment
eezstreet Posted April 22, 2016 Share Posted April 22, 2016 Hi, There are two problems with your code:For starters, only the first shot will ever fire. You need to loop through the four shots like this: for (currentShot = 1; currentShot <= 4; currentShot++) { ... } Your switch would be where the ... are now. You can remove the default case of your switch then, since it starts from 0. I forgot what the second thing was, but maybe you can tell me which commented line is breaking it? Link to comment
Teancum Posted April 22, 2016 Author Share Posted April 22, 2016 It was pretty much what you laid out. I figured out it would only fire from the default case. I hadn't thought of a for loop. That should work. ***EDIT***Here's what I've got now. I know I've referenced it wrong in the for loop as barrel shows as invalid. Looking up how to do it right. vec3_t offset; vec3_t barrel1; barrel1[0] = 22.0; barrel1[1] = 0.0; barrel1[2] = 0.0; vec3_t barrel2; barrel2[0] = 11.0; barrel2[1] = 0.0; barrel2[2] = 0.0; vec3_t barrel3; barrel3[0] = -11.0; barrel3[1] = 0.0; barrel3[2] = 0.0; vec3_t barrel4; barrel4[0] = -22.0; barrel4[1] = 0.0; barrel4[2] = 0.0; vec3_t shotVec; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall WP_MissileTargetHint(ent, start, forwardVec); /*missile = CreateMissile(start, forwardVec, DEMP2_VELOCITY, 10000, ent);*/ for (currentShot = 1; currentShot <= 4; currentShot++) { if (currentShot == 1) { VectorAdd(start, barrel1, shotVec); missile = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); } else if (currentShot == 2) { VectorAdd(start, barrel2, shotVec); missile = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); } else if (currentShot == 3) { VectorAdd(start, barrel3, shotVec); missile = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); } else { VectorAdd(start, barrel4, shotVec); missile = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); } } Link to comment
eezstreet Posted April 22, 2016 Share Posted April 22, 2016 shotVec is not getting set prior to being added to, so it will likely crash there. Also this code will not get the result that you expect anyway, since shotVec is being altered in each iteration of the loop.Another thing, this will not actually take the player's viewaxis into account. It will just fire 4 bolts in a straight line, at a 90 degree angle, regardless of where the player is looking.Here's something that should work, although it won't fix the viewaxis issue. I will have to think about how to fix this. vec3_t offset; vec3_t barrel[] = { {22.0f, 0.0f, 0.0f}, {11.0f, 0.0f, 0.0f}, {-11.0f, 0.0f, 0.0f}, {-22.0f, 0.0f, 0.0f} }; vec3_t shotVec; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall WP_MissileTargetHint(ent, start, forwardVec); /*missile = CreateMissile(start, forwardVec, DEMP2_VELOCITY, 10000, ent);*/ for (currentShot = 0; currentShot <= 3; currentShot++) // note the difference here { VectorCopy(muzzle, shotVec); VectorAdd(shotVec, barrel[i], shotVec); missile = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); } Link to comment
ensiform Posted April 22, 2016 Share Posted April 22, 2016 In the original code there is also the issue that the barrel is essentially a global in respect to all entities. Since this function is called everytime any player, NPC, or shooter map entity shoots this weapon it would not work so well. Link to comment
Teancum Posted April 23, 2016 Author Share Posted April 23, 2016 Yeah, I think I'll have to store an external cvar for the current barrel or something, as all the variables set get destroyed and reinitialized with each shot. Link to comment
Teancum Posted April 23, 2016 Author Share Posted April 23, 2016 Ugh. Well at least I can do the secondary fire. I just have to fire four projectiles at once and that can all happen in the same call of the function. I'll take care of that then move on to the Mortar Gun I suppose. ***EDIT*** @@ensiform -- why wouldn't setting a cvar work? I could initialize it in g_main.cpp and then update it using similar code. Can I not set a cvar from a weapon function? I know it's a bit nasty, but having four cvars (A,B,C,D) for the four barrels, turning them on and off and reading them each cycle might work. Link to comment
ensiform Posted April 24, 2016 Share Posted April 24, 2016 It would be ugly and slow for performance and exploitable. Plus cvars aren't meant for that. Link to comment
Teancum Posted April 24, 2016 Author Share Posted April 24, 2016 Any ideas? Perhaps a global within the C++ code? Like perhaps initializing the variable for looping elsewhere and then in wp_fusion.cpp extern int currentShot;Also two other quick questions:Can I specify a secondary hard-read folder? I want to do without the -path switch for /dfmod and have it hard coded along with the /base folder. -----Yep, in files.cpp, FS_BuildOSPath()Is there a command to write debug info to the console? That'd be incredibly helpful. -- Yep, the function is Com_Printf("TEXT MESSAGE", parameter2); Link to comment
ensiform Posted April 24, 2016 Share Posted April 24, 2016 No no. Needs to be player or entity specific like I said. Link to comment
Teancum Posted April 25, 2016 Author Share Posted April 25, 2016 So some progress has been made. I programmed the secondary fire, but the four barrels are offsetting relative to the hard vectors in the gameplay world, and not the player's direction. Here's the code for secondary fire: //--------------------------------------------------------- static void WP_DEMP2_AltFire( gentity_t *ent ) //--------------------------------------------------------- { vec3_t start; int damage = weaponData[WP_DEMP2].damage; gentity_t *missileA, *missileB, *missileC, *missileD; vec3_t barrelA = { -60.0f, -20.0f, 0.0f }; vec3_t barrelB = { 35.0f, -20.0f, 0.0f }; vec3_t barrelC = { -35.0f, -20.0f, 0.0f }; vec3_t barrelD = { -60.0f, -20.0f, 0.0f }; vec3_t shotVec; VectorCopy(muzzle, start); WP_TraceSetStart(ent, start, vec3_origin, vec3_origin); //make sure our start point isn't on the other side of a wall //Calculate damages if (ent->s.number != 0) { if (g_spskill->integer == 0) { damage = DEMP2_NPC_DAMAGE_EASY; } else if (g_spskill->integer == 1) { damage = DEMP2_NPC_DAMAGE_NORMAL; } else { damage = DEMP2_NPC_DAMAGE_HARD; } } //Barrel A WP_MissileTargetHint(ent, start, forwardVec); VectorMA(start, 1, barrelA, shotVec); //VectorAdd(start, barrelA, shotVec); missileA = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); //Com_Printf(S_COLOR_YELLOW "wp_demp2.cpp - firing secondary mode, barrel A", "barrel A"); missileA->classname = "demp2_proj"; missileA->s.weapon = WP_DEMP2; VectorSet(missileA->maxs, DEMP2_SIZE, DEMP2_SIZE, DEMP2_SIZE); VectorScale(missileA->maxs, -1, missileA->mins); missileA->damage = damage; missileA->dflags = DAMAGE_DEATH_KNOCKBACK; missileA->methodOfDeath = MOD_DEMP2; missileA->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missileA->bounceCount = 0; // we don't want it to ever bounce //Barrel B WP_MissileTargetHint(ent, start, forwardVec); VectorMA(start, 1, barrelB, shotVec); //VectorAdd(start, barrelB, shotVec); missileB = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); //Com_Printf("wp_demp2.cpp - firing secondary mode, barrel B", "barrel B"); missileB->classname = "demp2_proj"; missileB->s.weapon = WP_DEMP2; VectorSet(missileB->maxs, DEMP2_SIZE, DEMP2_SIZE, DEMP2_SIZE); VectorScale(missileB->maxs, -1, missileB->mins); missileB->damage = damage; missileB->dflags = DAMAGE_DEATH_KNOCKBACK; missileB->methodOfDeath = MOD_DEMP2; missileB->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missileB->bounceCount = 0; // we don't want it to ever bounce //Barrel C WP_MissileTargetHint(ent, start, forwardVec); VectorMA(start, 1, barrelC, shotVec); //VectorAdd(start, barrelC, shotVec); missileC = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); //Com_Printf("wp_demp2.cpp - firing secondary mode, barrel C", "barrel C"); missileC->classname = "demp2_proj"; missileC->s.weapon = WP_DEMP2; VectorSet(missileC->maxs, DEMP2_SIZE, DEMP2_SIZE, DEMP2_SIZE); VectorScale(missileC->maxs, -1, missileC->mins); missileC->damage = damage; missileC->dflags = DAMAGE_DEATH_KNOCKBACK; missileC->methodOfDeath = MOD_DEMP2; missileC->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missileC->bounceCount = 0; // we don't want it to ever bounce //Barrel D WP_MissileTargetHint(ent, start, forwardVec); VectorMA(start, 1, barrelD, shotVec); //VectorAdd(start, barrelD, shotVec); missileD = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); //Com_Printf("wp_demp2.cpp - firing secondary mode, barrel D", "barrel D"); missileD->classname = "demp2_proj"; missileD->s.weapon = WP_DEMP2; VectorSet(missileD->maxs, DEMP2_SIZE, DEMP2_SIZE, DEMP2_SIZE); VectorScale(missileD->maxs, -1, missileD->mins); missileD->damage = damage; missileD->dflags = DAMAGE_DEATH_KNOCKBACK; missileD->methodOfDeath = MOD_DEMP2; missileD->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missileD->bounceCount = 0; // we don't want it to ever bounce } And for primary fire I've tried the idea that @@ensiform had of tying it to the player/entity. I looked at how the rocket launcher hooked up the tracking values, and came up with this in g_weapon.cpp. Basically each time it's called it'll increment the barrel number and output it. // some naughty little things that are used cg side int g_rocketLockEntNum = ENTITYNUM_NONE; int g_rocketLockTime = 0; int g_rocketSlackTime = 0; int currentFusionShot = 0; //to loop through fusion rifle barrels ...... //----------------------------------------------------------------------------- void WP_fusionBarrel(int currentFusionShot) //----------------------------------------------------------------------------- { //whenever this is called, it will increment the number (max of 3, then returns to 0) //it will then pass that information to wp_fusion.cpp currentFusionShot++; if ( currentFusionShot >= 3 ) { currentFusionShot = 0; } } From there I run the function in wp_fusion.cpp to grab the current int. However it's still not outputting a number to the console, so I can't tell if its actually iterating, or even if it's pulling the value from g_weapon.cpp //--------------------------------------------------------- static void WP_DEMP2_MainFire( gentity_t *ent ) //--------------------------------------------------------- { vec3_t start; int damage = weaponData[WP_DEMP2].damage; gentity_t *missile; vec3_t barrel[] = { { 22.0f, 0.0f, 0.0f }, { 11.0f, 0.0f, 0.0f }, { -11.0f, 0.0f, 0.0f }, { -22.0f, 0.0f, 0.0f } }; vec3_t shotVec; VectorCopy(muzzle, start); WP_TraceSetStart(ent, start, vec3_origin, vec3_origin);//make sure our start point isn't on the other side of a wall WP_MissileTargetHint(ent, start, forwardVec); /*missile = CreateMissile(start, forwardVec, DEMP2_VELOCITY, 10000, ent);*/ WP_fusionBarrel(currentShot); //get the current barrel number from g_weapon.cpp and store it Com_Printf(S_COLOR_YELLOW "wp_demp2.cpp - firing primary mode, barrel #", currentShot); for (currentShot = 0; currentShot <= 3; currentShot++) { VectorCopy(muzzle, shotVec); VectorAdd(shotVec, barrel[currentShot], shotVec); missile = CreateMissile(shotVec, forwardVec, DEMP2_VELOCITY, 10000, ent); } missile->classname = "demp2_proj"; missile->s.weapon = WP_DEMP2; // Do the damages if ( ent->s.number != 0 ) { if ( g_spskill->integer == 0 ) { damage = DEMP2_NPC_DAMAGE_EASY; } else if ( g_spskill->integer == 1 ) { damage = DEMP2_NPC_DAMAGE_NORMAL; } else { damage = DEMP2_NPC_DAMAGE_HARD; } } VectorSet( missile->maxs, DEMP2_SIZE, DEMP2_SIZE, DEMP2_SIZE ); VectorScale( missile->maxs, -1, missile->mins ); missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_DEMP2; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; // we don't want it to ever bounce missile->bounceCount = 0; } I have to say, being able to spit out debug info to the console is super nice. Glad I found that function. Link to comment
eezstreet Posted April 26, 2016 Share Posted April 26, 2016 Yes, I mentioned that this would be an issue earlier. I can't remember off the top of my head how I handle this. I believe the way to do it is involves axes/axis functions? Dunno. Maybe @@Scooper knows, I always defer vector-related questions to him. Link to comment
Scooper Posted April 29, 2016 Share Posted April 29, 2016 Hey, didn't notice the notifaction for a few days. Been very busy. You could try something like this. Not 100% sure if it will compile, didn't test it =p Good luck. //--------------------------------------------------------- void G_CreateRotationMatrix(vec3_t angles, matrix3_t matrix); // Function decleration/prototype so we can use it. You can put this in a header file. static void WP_DEMP2_AltFire( gentity_t *ent ) //--------------------------------------------------------- { int damage = weaponData[WP_DEMP2].damage; int currentShot = 0; vec3_t start; matrix3_t rotMatrix; vec3_t barrel[] = { {22.0f, 0.0f, 0.0f}, {11.0f, 0.0f, 0.0f}, {-11.0f, 0.0f, 0.0f}, {-22.0f, 0.0f, 0.0f} }; VectorCopy(muzzle, start); WP_TraceSetStart(ent, start, vec3_origin, vec3_origin); //make sure our start point isn't on the other side of a wall //Calculate damages if (ent->s.number != 0) { if (g_spskill->integer == 0) { damage = DEMP2_NPC_DAMAGE_EASY; } else if (g_spskill->integer == 1) { damage = DEMP2_NPC_DAMAGE_NORMAL; } else { damage = DEMP2_NPC_DAMAGE_HARD; } } // I don't have the source for this function, not 100% sure what it does. // I assume it finds and adjusted muzzle point as well as the forward vector of the player. WP_MissileTargetHint(ent, start, forwardVec); // Create a rotation matrix from the player view angles. G_CreateRotationMatrix(ent->client->ps.viewangles, rotMatrix); for (currentShot = 0; currentShot <= 3; currentShot++) { vec3_t muzzleOffset; VectorCopy(barrel[currentShot], muzzleOffset); RotatePoint(muzzleOffset, rotMatrix); // Rotate the current barrel/muzzle offset to be relative to the player rotation. VectorAdd(start, muzzleOffset, muzzleOffset); missile = CreateMissile( muzzleOffset, forwardVec, DEMP2_VELOCITY, 10000, ent); missile->classname = "demp2_proj"; missile->s.weapon = WP_DEMP2; VectorSet(missileA->maxs, DEMP2_SIZE, DEMP2_SIZE, DEMP2_SIZE); VectorScale(missileA->maxs, -1, missileA->mins); missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_DEMP2; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missile->bounceCount = 0; // we don't want it to ever bounce } } Futuza and Teancum like this Link to comment
Teancum Posted April 30, 2016 Author Share Posted April 30, 2016 Thanks much. I'll give it a try. Link to comment
Teancum Posted May 12, 2016 Author Share Posted May 12, 2016 I've decided to shelve the Fusion Cutter. Even using AngleVectors() then VectorScale() to get the right-angle vector relative to the player, the move it out each time the gun is fired makes no difference. The projectile switches sides from right to left as you rotate the player and fire. It's not worth the time to write something totally custom, and would take a lot of trigonometry/calc to do so. ***EDIT*** This bit of code from g_weapon.cpp might hold a clue. It seems to deal with each axis of the vector separately rather than trying to do so all at once. Posting it here mostly so I remember to look at it later. Additional comments have been added by me // Muzzle point table... vec3_t WP_MuzzlePoint[WP_NUM_WEAPONS] = {// Fwd, right, up. {0, 0, 0 }, // WP_NONE, {8 , 16, 0 }, // WP_SABER, {12, 6, -6 }, // WP_BLASTER_PISTOL, {12, 6, -6 }, // WP_BLASTER, {12, 6, -6 }, // WP_DISRUPTOR, {12, 2, -6 }, // WP_BOWCASTER, {12, 4.5, -6 }, // WP_REPEATER, {12, 6, -6 }, // WP_DEMP2, {12, 6, -6 }, // WP_FLECHETTE, {12, 8, -4 }, // WP_ROCKET_LAUNCHER, {12, 0, -4 }, // WP_THERMAL, {12, 0, -10 }, // WP_TRIP_MINE, {12, 0, -4 }, // WP_DET_PACK, {12, 8, -4 }, // WP_CONCUSSION, {0 , 8, 0 }, // WP_MELEE, {0, 0, 0 }, // WP_ATST_MAIN, {0, 0, 0 }, // WP_ATST_SIDE, {0 , 8, 0 }, // WP_STUN_BATON, {12, 6, -6 }, // WP_BRYAR_PISTOL, }; void WP_RocketLock( gentity_t *ent, float lockDist ) { // Not really a charge weapon, but we still want to delay fire until the button comes up so that we can // implement our alt-fire locking stuff vec3_t ang; trace_t tr; vec3_t muzzleOffPoint, muzzlePoint, forwardVec, right, up; AngleVectors( ent->client->ps.viewangles, forwardVec, right, up ); //Get the forward, right and up axes to form a vector based on our angle AngleVectors(ent->client->ps.viewangles, ang, NULL, NULL); //do it again, but save only the forward as "ang" VectorCopy( ent->client->ps.origin, muzzlePoint ); //copy the player's origin as "muzzlePoint" VectorCopy(WP_MuzzlePoint[WP_ROCKET_LAUNCHER], muzzleOffPoint); //Copy the muzzle point from the table above as "muzzleOffPoint" VectorMA(muzzlePoint, muzzleOffPoint[0], forwardVec, muzzlePoint); //forwardVec * the forward vector from muzzleOffPoint, add muzzlePoint, save as muzzlePoint VectorMA(muzzlePoint, muzzleOffPoint[1], right, muzzlePoint); //do the same process for the right vector muzzlePoint[2] += ent->client->ps.viewheight + muzzleOffPoint[2]; //for the up vector, take the player's viewheight + the up vector from muzzleOffPoint ang[0] = muzzlePoint[0] + ang[0]*lockDist; ang[1] = muzzlePoint[1] + ang[1]*lockDist; ang[2] = muzzlePoint[2] + ang[2]*lockDist; gi.trace(&tr, muzzlePoint, NULL, NULL, ang, ent->client->ps.clientNum, MASK_PLAYERSOLID, (EG2_Collision)0, 0); if (tr.fraction != 1 && tr.entityNum < ENTITYNUM_NONE && tr.entityNum != ent->client->ps.clientNum) { gentity_t *bgEnt = &g_entities[tr.entityNum]; if ( bgEnt && (bgEnt->s.powerups&PW_CLOAKED) ) { ent->client->rocketLockIndex = ENTITYNUM_NONE; ent->client->rocketLockTime = 0; } else if (bgEnt && bgEnt->s.eType == ET_PLAYER ) { if (ent->client->rocketLockIndex == ENTITYNUM_NONE) { ent->client->rocketLockIndex = tr.entityNum; ent->client->rocketLockTime = level.time; } else if (ent->client->rocketLockIndex != tr.entityNum && ent->client->rocketTargetTime < level.time) { ent->client->rocketLockIndex = tr.entityNum; ent->client->rocketLockTime = level.time; } else if (ent->client->rocketLockIndex == tr.entityNum) { if (ent->client->rocketLockTime == -1) { ent->client->rocketLockTime = ent->client->rocketLastValidTime; } } if (ent->client->rocketLockIndex == tr.entityNum) { ent->client->rocketTargetTime = level.time + 500; } } } else if (ent->client->rocketTargetTime < level.time) { ent->client->rocketLockIndex = ENTITYNUM_NONE; ent->client->rocketLockTime = 0; } else { if (ent->client->rocketLockTime != -1) { ent->client->rocketLastValidTime = ent->client->rocketLockTime; } ent->client->rocketLockTime = -1; } } Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now