Genesis3D Programming - Genesis3D University is your resource for Genesis3D Game development



mainpage_menu.gif (4453 bytes)
2dart_menu.gif (3990 bytes)
3dmodeling_menu.gif (4513 bytes)
leveldesign_menu.gif (4781 bytes)
prog_menu.gif (4927 bytes)
yools_menu.gif (3923 bytes)
ref_menu.gif (4496 bytes)
links_meu.gif (4796 bytes)
forum_menu.gif (4089 bytes)
contact_menu.gif (4546 bytes)

Download 
Genesis3D v1.1

G3DU Forum

Official Forum


Free web hosting


Programming
http://Welcome.to/Genesis3D-University 

Flame Thrower

For

GTest 1.1

 

By: David Bonolo

Hi again. This is my third tutorial. I will show you how to make a flame thrower for GTest. This is somewhat what it looks like:

 

 

The code is basically just the Blaster code copied over, but modified. Let’s begin.

All code changes are done in Yellow.

 

Go to the FireBlaster function in Weapon.c. Add at the end, about line 1043 or so, add this large block of code:

//================================================

//          Flame_Control

//================================================

geBoolean Flame_Control(GenVSI *VSI, void *PlayerData, float Time)

{

            geVec3d          In, Front, Back;
            geXForm3d        DestXForm;
           
GE_Collision     Collide;
            float            Speed;
            GPlayer          *Player;
            geWorld          *World;
            CData            Data;

            Player = (GPlayer*)PlayerData;

            Player->Time += Time;

            Speed = Player->Time*3600.0f;

            if (Speed > 4000.0f)
                       
Speed = 4000.0f;

            geXForm3d_Copy(&Player->XForm, &DestXForm);

            geXForm3d_GetIn(&Player->XForm, &In);

            geVec3d_Scale(&In, Speed*Time, &In);         

            geXForm3d_Translate(&DestXForm, In.X, In.Y, In.Z);

            geXForm3d_GetIn(&Player->XForm, &In);

            geVec3d_Scale(&In, 500.f, &Player->Velocity);

            Front = Player->XForm.Translation;

            Back = DestXForm.Translation;

            geXForm3d_Copy(&DestXForm, &Player->XForm);

            World = GenVSI_GetWorld(VSI);

 

            assert(World);

            Data.VSI = VSI;

            Data.Player = Player;

            if (geWorld_Collision(World, NULL, NULL, &Front, &Back,
                GE_CONTENTS_CANNOT_OCCUPY,
                GE_COLLIDE_MODELS|GE_COLLIDE_ACTORS, 
                0xffffffff, SelfCollisionCB, &Data, &Collide))

            {

               Player->XForm.Translation = Collide.Impact;

               geVec3d_AddScaled(&Player->XForm.Translation,
                    &Collide.Plane.Normal, 40.0f, &Player->XForm.Translation);

               if (Collide.Model)
               {

                    GPlayer                        *Target;

                    Target = (GPlayer*)geWorld_ModelGetUserData(Collide.Model);

                    if (Target && Target->Trigger && Target->ViewFlags &
                            VIEW_TYPE_PHYSOB)
                    {
                         
Target->Trigger(VSI, Target, Player, (void*)&Collide);
                    }

                }

                 //if (VSI->Mode == MODE_Server)

                   {

                      if (Collide.Actor)

                      {

                        GPlayer      *PlayerHit;

                        PlayerHit = GenVSI_ActorToPlayer(VSI, Collide.Actor);

                        if (PlayerHit && PlayerHit != Player->Owner) 

                            DammagePlayer(VSI, Player, PlayerHit, 15,
                                    BLASTER_POWER,Time);

                      }

                      else

                           RadiusDammage(VSI, Player, 10, BLASTER_POWER_RADIUS,
                                    BLASTER_RADIUS, Time);

                   }

 

             GenVSI_SpawnFx(VSI, FX_EXPLODE2, &Player->XForm.Translation,
                        SOUND_INDEX_BLASTER_BANG);

             

              GenVSI_DestroyPlayer(VSI, PlayerData);

            }

            

            if (Player->Time >= 0.40f)      // Kill it after god only knows

            GenVSI_DestroyPlayer(VSI, PlayerData);

 

            Player->VPos = Player->XForm.Translation;

 

            return GE_TRUE;

}

 

//===================================================

//          FireFlame

//===================================================

void FireFlame(GenVSI *VSI, void *PlayerData, float Time)

{

            GPlayer          *Weapon;

            geVec3d          Up, In, Rt, Front, Back, Impact;

            GE_Collision     Collision;

            geWorld          *World;

            GPlayer          *Player;

            CData            Data;

 

            Player = (GPlayer*)PlayerData;

            Weapon = GenVSI_SpawnPlayer(VSI, "Weapon_Flame");

 

            if (!Weapon)

            {

                   GenVSI_ConsolePrintf(VSI, "FireFlame:  Failed to add player.\n");

                      return;

            }

 

            // Setup the callbacks for this weapon

            Weapon->Control = Flame_Control;

            Weapon->Blocked = NULL;

            Weapon->Trigger = NULL;

            Weapon->Owner = Player;

            Weapon->Time = 0.0f;

            Weapon->PingTime = Player->PingTime;

 

            geVec3d_Set(&Weapon->Mins, -10.0f, -10.0f, -10.0f);

            geVec3d_Set(&Weapon->Maxs,  10.0f,  10.0f,  10.0f);

 

            Weapon->ControlIndex = 5;

 

            Weapon->ViewFlags = (VIEW_TYPE_SPRITE | VIEW_TYPE_LIGHT);

            Weapon->ViewIndex = TEXTURE_INDEX_WEAPON2;

            Weapon->Scale = 3.5f;

            Weapon->FxFlags = FX_EXPLODE2;   // Make some flames follow Weapon_Flame

 

            Weapon->XForm = Player->XForm;

            

            geVec3d_Add(&Weapon->XForm.Translation, &Player->GunOffset,
                        &Weapon->XForm.Translation);

 

            geXForm3d_GetIn(&Weapon->XForm, &In);

            geXForm3d_GetUp(&Weapon->XForm, &Up);

            geXForm3d_GetLeft(&Weapon->XForm, &Rt);

 

            Front = Weapon->XForm.Translation;

 

            geVec3d_AddScaled(&Front, &In, 10000.0f, &Back);

 

            World = GenVSI_GetWorld(VSI);

            assert(World);

 

            // Find out what direction the rocket needs to go to hit
            // the target in the center of the screen

            if (geWorld_Collision(World, NULL, NULL, &Front, &Back,
                    GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_ALL, 0, 
                    NULL, NULL, &Collision))

                        Impact = Collision.Impact;

            else

                        Impact = Back;

  

            // Position the Weapon_Blaster under the lower left arm

            geVec3d_AddScaled(&Front, &In, 70.0f, &Front);

            geVec3d_AddScaled(&Front, &Up, -10.0f, &Front);

            geVec3d_AddScaled(&Front, &Rt, -10.0f, &Front);

 

            XFormFromVector(&Front, &Impact, 0.0f, &Weapon->XForm);

 

            // HACK!!! Rocket is backwards, so rotate about up vector 180

            // Rotate the thing 180

 

            // Play the "take off" sound

            GenVSI_PlaySound(VSI, SOUND_INDEX_BLASTER, &Player->XForm.Translation);

 

             Player->NextWeaponTime = GenVSI_GetTime(VSI) + 0.0f;

 

            Player->VPos = Player->XForm.Translation;

 

            

  // This next part is the Decal Manager. If you don’t have it, take it out.

            if (geWorld_Collision(World, NULL, NULL, &Front, &Back,
                GE_CONTENTS_CANNOT_OCCUPY, GE_COLLIDE_MODELS, 0xffffffff,
                SelfCollisionCB, &Data, &Collision))

            {

                GE_RGBA RGBA_Array = {255, 255, 255, 200};

                DecalMgr_AddDecal(Globals.dMgr, DECAL_SCORCHMED1, -1.0f, 
                            RGBA_Array, 1.0f, &Collision.Impact,
                            &Collision.Plane.Normal, &Collision.Impact);

             }

            // This ends the Decal Manager.

}

 

Remember, if you don’t use the DecalManager, take it out. Next got the FireWeapon function. Add:

 

case 5:

FireFlame(VSI, Player, Time);

            break;

 

Make sure the case is the next weapon. It’s not good to skip any numbers. Next, in GMain.c, about line 123, add:

 

GenVSI_SetClassSpawn(VSI, "ItemShredder", Item_ShredderSpawn, NULL);

GenVSI_SetClassSpawn(VSI, "ItemShredderAmmo", Item_ShredderAmmoSpawn, NULL);

GenVSI_SetClassSpawn(VSI, "ItemFlame", Item_FlameSpawn, NULL);

GenVSI_SetClassSpawn(VSI, "ItemFlameAmmo", Item_FlameAmmoSpawn, NULL);

 

GenVSI_SetClassSpawn(VSI, "AttackerTurret", Attacker_TurretSpawn, Attacker_TurretDestroy);

 

Then, about 146, add:

GenVSI_ProcIndex(VSI, 9, Item_ControlHealth);

GenVSI_ProcIndex(VSI, 11, Flame_Control);

 

Then, about 167:

GenVSI_ProcIndex(VSI, 8, Shredder_Control);

GenVSI_ProcIndex(VSI, 9, Item_ControlHealth);

GenVSI_ProcIndex(VSI, 10, Flame_Control);

 

Then, 340:

GenVSI_SetClientInventory(VSI, Player->ClientHandle, ITEM_SHREDDER, 0, GE_FALSE);

GenVSI_SetClientInventory(VSI, Player->ClientHandle, ITEM_FLAME, 0, GE_FALSE);

 

Now, in GMain.h, about line 39:

#define ACTOR_INDEX_ARMOR       9

#define ACTOR_INDEX_FLAME       10

#define ACTOR_INDEX_FLAME_AMMO  11

 

About line 87:

#define ITEM_ROCKETS            2

#define ITEM_SHREDDER           3

#define ITEM_FLAME              4

 

About 133:

// Flame

#define FLAME_RESPAWN           10.0f

#define FLAME_AMMO_RESPAWN      30.0f

 

#define FLAME_AMOUNT            25

#define FLAME_MAX_AMOUNT        200

#define FLAME_AMMO_AMOUNT       50

 

Line 202:

geBoolean        Shredder_Control(GenVSI *VSI, void *PlayerData, float Time);

geBoolean        Flame_Control(GenVSI *VSI, void *PlayerData, float Time);

 

Line 218:

geBoolean        Item_ShredderSpawn(GenVSI *VSI, void *PlayerData, void *ClassData,
                                        char *EntityName);

geBoolean        Item_ShredderAmmoSpawn(GenVSI *VSI, void *PlayerData, 
                                        void *ClassData, char *EntityName);

geBoolean        Item_FlameSpawn(GenVSI *VSI, void *PlayerData, 
                                        void *ClassData, char *EntityName);

geBoolean        Item_FlameAmmoSpawn(GenVSI *VSI, void *PlayerData, 
                                        void *ClassData, char *EntityName);

 

In Genvs.h, add somewhere in the file:

// ItemFlame

#pragma GE_Type("Item.ico")

typedef struct  ItemFlame

{

#pragma GE_Published

    geVec3d                  Origin;

#pragma GE_Origin(Origin)

}   ItemFlame;

 

// ItemFlameAmmo

#pragma GE_Type("Item.ico")

typedef struct  ItemFlameAmmo

{

#pragma GE_Published

    geVec3d                  Origin;

#pragma GE_Origin(Origin)

}   ItemFlameAmmo;

 

Now, in Items.c, add this big block at about line 241:

//=================================================

//          Item_ControlFlame

//=================================================

static geBoolean Item_ControlFlame(GenVSI *VSI, void *PlayerData, float Time)

{

            geVec3d          Pos;

            GPlayer          *Player;

 

            Player = (GPlayer*)PlayerData;

 

            if (GenVSI_GetTime(VSI) < Player->NextThinkTime)

                        return GE_TRUE;

 

            if (Player->ViewIndex == 0xffff)

            {

                GenVSI_SpawnFx(VSI, FX_EXPLODE2, &Player->XForm.Translation,
                                SOUND_INDEX_ITEM_SPAWN);

                 Player->ViewIndex = ACTOR_INDEX_SHREDDER;

            }

           

            Pos = Player->XForm.Translation;

            geXForm3d_RotateY(&Player->XForm, Time*2.0f);

            Player->XForm.Translation = Pos;

            return GE_TRUE;

}

 

//================================================

//          Item_ControlFlameAmmo

//================================================

static geBoolean Item_ControlFlameAmmo(GenVSI *VSI, void *PlayerData, float Time)

{

            GPlayer            *Player;

            Player = (GPlayer*)PlayerData;

 

            if (GenVSI_GetTime(VSI) < Player->NextThinkTime)

                        return GE_TRUE;

 

            if (Player->ViewIndex == 0xffff)     // Time to respawn

            {

                 GenVSI_SpawnFx(VSI, FX_EXPLODE2, &Player->XForm.Translation,
                                SOUND_INDEX_ITEM_SPAWN);

                 Player->ViewIndex = ACTOR_INDEX_SHREDDER_AMMO;

            }

           

            return GE_TRUE;

}

 

//===================================================

//          Item_TriggerFlame

//===================================================

static geBoolean Item_TriggerFlame(GenVSI *VSI, void *PlayerData, 
                                        void *TargetData, void* data)

{

            GPlayer   *Player, *Target;

            Player = (GPlayer*)PlayerData;

            Target = (GPlayer*)TargetData;

 

            if (GenVSI_GetTime(VSI) < Player->NextThinkTime)

                        return GE_TRUE;

 

            if (Target->ClientHandle == CLIENT_NULL_HANDLE)

                        return GE_TRUE;

 

            if (Target->InventoryHas[ITEM_FLAME])

                        return GE_TRUE;

 

            // Make the ammo dissapear

            Player->ViewIndex = 0xffff;

            Player->NextThinkTime = GenVSI_GetTime(VSI) + FLAME_RESPAWN;                // Make them come back at a later time

 

            GenVSI_PlaySound(VSI, SOUND_INDEX_PICKUP_WEAPON2,
                            &Player->XForm.Translation);

 

            Target->InventoryHas[ITEM_FLAME] = GE_TRUE;

            Target->CurrentWeapon = ITEM_FLAME;

 

            if (Target->ClientHandle != CLIENT_NULL_HANDLE)

                        GenVSI_SetClientWeapon(VSI, Target->ClientHandle, ITEM_FLAME);

                       

            Target->Inventory[ITEM_FLAME] += FLAME_AMOUNT;

           

            // Actors don't have a client handle

            if (Target->ClientHandle != CLIENT_NULL_HANDLE)

            {

                  UpdateClientInventory(VSI, Target, ITEM_FLAME);

                  GenVSI_ConsoleHeaderPrintf(VSI, Target->ClientHandle, 
                        GE_FALSE, "You get the Flame Thrower");

            }

 

            return GE_TRUE;

}

 

//=====================================================

//          Item_TriggerFlameAmmo

//=====================================================

static geBoolean Item_TriggerFlameAmmo(GenVSI *VSI, void *PlayerData, void *TargetData, void* data)

{

            GPlayer     *Player, *Target;

 

            Player = (GPlayer*)PlayerData;

            Target = (GPlayer*)TargetData;

 

            if (GenVSI_GetTime(VSI) < Player->NextThinkTime)

                        return GE_TRUE;

 

            if (Target->ClientHandle == CLIENT_NULL_HANDLE)

                        return GE_TRUE;

 

            if (Target->Inventory[ITEM_FLAME] >= FLAME_MAX_AMOUNT)

                        return GE_TRUE;

 

            // Make the ammo disappear

            Player->ViewIndex = 0xffff;

            Player->NextThinkTime = GenVSI_GetTime(VSI) + FLAME_AMMO_RESPAWN;             // Make them come back at a later time

 

            // Increase the items of the player the touches this ammo

            Target->Inventory[ITEM_FLAME] += FLAME_AMMO_AMOUNT;

           

            if (Target->Inventory[ITEM_FLAME] > FLAME_MAX_AMOUNT)

                        Target->Inventory[ITEM_FLAME] = FLAME_MAX_AMOUNT;

                       

            GenVSI_PlaySound(VSI, SOUND_INDEX_PICKUP_WEAPON1,
                            &Player->XForm.Translation);

 

            // Actors don't have a client handle

            if (Target->ClientHandle != CLIENT_NULL_HANDLE)

            {

                  UpdateClientInventory(VSI, Target, ITEM_FLAME);

                  GenVSI_ConsoleHeaderPrintf(VSI, Target->ClientHandle,
                                GE_FALSE, "You picked up some gas tanks");

            }

 

            return GE_TRUE;

}

 

I think that’s about it. Just make an actor, define all the actor indexes, and change all the code above to point to your flame thrower actor and ammo. With the way the code is, you will die very quickly. It shoots so fast, it’s over before you even knew it begun. If you want a longer flame, just change:

 

if (Player->Time >= 0.40f)

GenVSI_DestroyPlayer(VSI, PlayerData);

 

That number is the time when it will stop. The bigger the number, the longer the stream. You’ll also probably want to change the FX system to your own, but the included FX works fine. Plenty of fire and plenty of smoke. E-mail me at bonolo1@core.com


 

Get Genesis3D University on CD !

The Genesis3d UNIVERSITY [G3DU] CD 
Many tutorials, file downloads and more, all on one CD, imagine that! 
Over 530 megs of files!  Just look over all of this website, to  get an idea of the CD contents. 

To review the CD content and to Find out how to get yours.  HERE

******

 

 

 

To report "errors" and to post comments e-mail us at KenDeel@mail.com

This Website Created and Hosted by OtherWorlds InterActive.
Copyright (c)1999-2001 OtherWorlds InterActive 
All rights reserved.