dev documents

All the old development documents I found on my back up drives.
This commit is contained in:
revility 2018-10-03 07:11:00 -04:00 committed by Daniel Gibson
parent 1f82525502
commit 5917d607ce
11 changed files with 1434 additions and 0 deletions

8
documents/README.txt Normal file
View file

@ -0,0 +1,8 @@
This folder contains many of the old development documents used during development of the Rivensin Mod.
I kept track of everything during development of the mod... almost everything was logged.
This included tutorials we used to get the grabber in vanilla doom 3, and getting the thirdperson camera going.
Note that nothing in this folder has been proof read.... spelling and grammer will be wonky.
Any questions just ask Revility

View file

@ -0,0 +1 @@
THIRD_PERSON_FOCUS_DISTANCE = 512.0f;

View file

@ -0,0 +1,4 @@
pm_thirdPersonSideScale: used to move the camera sideways. 0 is center.
pm_thirdPersonAngle: used to move the camera around the player. 0 is behind.
pm_thirdPersonHeight: Used to move the camera up and down
pm_thirdPersonRange: Move the camera closer or further away from the player.

View file

@ -0,0 +1,366 @@
The following read me file contains various notes by Ivan_the_B about the new melee attack system, combo system, dynamic spread spread system and the dynamic pain system.
notes compiles together on 10.14.08 by Revility. Any changes or additions to the systems will be added as needed.
//--------------------------------------------------------------------------------
//Melee System
//--------------------------------------------------------------------------------
- How it works (quick overview):
If the weapon worldmodel has the joint "melee", a tracer is fired from that joint in its direction, otherwise is fired from the player vieworigin, as the default D3 melee.
The width of the tracer is determined by the "melee_tracerWidth" key in the weapon def. A value of "0" means that the tracer is nothing more than a line.
The lenght of the tracer is determined by the "melee_distance" key in the weapon def.
The damagedef is determined by the "def_melee" key in the weapon def.
- New weapon scriptevents:
the old "melee()" scriptevent could be used, but what makes all this so easy to use are these new scriptevents:
Code:
void startAutoMelee( float dmgMult ); //specify the damage multiplier of this attack...very useful for combo ;D
void stopAutoMelee(); //stop if active!
Once "startAutoMelee" is started, the game automatically performs something very close to "melee()" every tick, until "stopAutoMelee()" is called.
Plus, it automatically ignores the last entity hit since "startAutoMelee" was started, so that it cannot happen that the same entity is constantly hit.
Starting again "startAutoMelee()" if it's already active resets the last entity hit to null, so this is a way to say "I can hit you again from now".
- How to use it:
Sure, you could call those scriptevents from your weapons, but what would allow us a far greater flexibility is calling them at a certain frame of the player animation.
That's why I've added the following funtions in the player scriptobject
Code:
startWeaponAutoMeleeX1(); //standard damage
startWeaponAutoMeleeX2(); //double damage
//...there are also X3 X4 X5 X10 X100, and you can easily add your own.
stopWeaponAutoMeleeAny(); //stop if active!
They simply call the "startAutoMelee" and "stopAutoMelee" scriptobject on the current weapon, specifing different damage multiplyers.
Example of the first attack animation for the ruinblade, from player.def.
Code:
anim ruinblade_punch_first models/md5/characters/npcs/playermoves/sword_swing1.md5anim{
frame 1 object_call startWeaponAutoMeleeX1 //start attack, standard damage
frame 9 object_call stopWeaponAutoMeleeAny //end attack
}
Note that I can choose to stop the attack at the frame 9 out of 15 because it fits the sword movement in the game.
Ruinblade scriptobject has been modified accordingly (it simply wait for the attack anim to end).
//--------------------------------------------------------------------------------
//Movements based on animations for the player
//--------------------------------------------------------------------------------
- How it works (quick overview):
I had to add a lot of stuff in Physics_Player.cpp to add a new movementType ( PM_ANIM ) based on animations delta.
Player scriptevents can enable/disable this new movementType.
While it's active: dodge, dash ,weapon change, ability to attack, player model turning and other movements are disabled.
The scriptobject of the current weapon is set in a new state called "WeaponWaiting" that should do nothing more than wait (could also stop sounds/effects if needed).
When it is disabled: all is reactivated and the scriptobject of the current weapon is set in it "idle" state.
- New player scriptevents:
Code:
void setAnimMoveOn();
void setAnimMoveOff();
- How to use it:
Don't use it
It should only be started/stopped by the following player function.
Quote
playCustomAnimMove(string animname, float blendIn, float blendOut, float gravityMult)
It plays the specified animation on full-body with the movementType based on animations delta.
Use this inside the function for comboes, decribed next.
"gravityMult" specifiles the gravity fot this animation. 1 means default gravity, 0 means no gravity, 0.5 half gravity, and so on...
You can also change it from the animation def thanks to the player functions
Code:
void enableGravityInAnimMoveX1();
void enableGravityInAnimMoveX05();
void disableGravityInAnimMoveAny();
example (assuming this anim has been started with gravity > 0):
Quote
anim ruinblade_combo_1 models/md5/characters/npcs/playermoves/comboanim.md5anim{ //gravity multiplier only works for combos
frame 1 sound_body player_sword_fire
frame 2 object_call startWeaponAutoMeleeX10 //start attack
frame 5 object_call disableGravityInAnimMoveAny //disable gravity
frame 13 object_call stopWeaponAutoMeleeAny //end attack
}
Note: No need to re-enable the gravity because the multiplier is only used while a combo is executed, not for normal movements.
//--------------------------------------------------------------------------------
//Adding a combo animation
//--------------------------------------------------------------------------------
Easy. Simply add the new animation in the player.def and start/stop sounds and attacks from there.
No need to add a corresponding anim in the weapon def.
Example:
Code:
anim ruinblade_combo_1 models/md5/characters/npcs/playermoves/sword_swing3.md5anim{ //to do: create a proper anim
frame 1 sound_body player_sword_fire
frame 2 object_call startWeaponAutoMeleeX10 //start attack
frame 13 object_call stopWeaponAutoMeleeAny //end attack
}
//--------------------------------------------------------------------------------
//Combo system
//--------------------------------------------------------------------------------
- How it works (quick overview):
Near the beginning of the player .script file, there's a new function.
Code:
void player::check_inputs()
This baby checks every frame the player inputs and store them, if needed, as flags in a float value (like the attack-choose system in every doom3 AI).
This means that you can store all the inputs states in a single float and check them later. What could be more handy and efficient?
The flags are:
FLAG_NULL //nothing is pressed
FLAG_RIGHT
FLAG_LEFT
FLAG_FORWARD
FLAG_BACKWARD
FLAG_FIREPRI
FLAG_FIRESEC
FLAG_JUMP
FLAG_CROUCH
- How to use it:
Hum.
Cold seems complex at first sight,but in reality it allows us to specify any sort of combo in a very simple way.
We have 7 variables
Code:
float flags_combo_now;
float flags_combo_1ago;
float flags_combo_2ago;
float flags_combo_3ago;
float flags_combo_4ago;
float flags_combo_5ago;
float flags_combo_6ago;
Each of them represents all the input states in different time instants.
I won't exaplain which are these instants (from here I'll call them "relevant instants" ), but just know that they are the useful ones.
"flags_combo_now" represents the actual input states.
//...
"flags_combo_6ago" represents the oldest input states we can remember about.
Now...
Let's start with an example.
We want to start a certain combo if we quickly press "crouch, crouch, forward".
First of all, you have to think it as "crouch, nothing, crouch, nothing, forward".
That is, if we use our flags: FLAG_CROUCH, FLAG_NULL, FLAG_CROUCH, FLAG_NULL, FLAG_FORWARD
Right?
Well, what we want is that
if(
the input states registered 4 "relevant instants" ago are == FLAG_CROUCH <--> (flags_combo_4ago == FLAG_CROUCH)
and
the input states registered 3 "relevant instants" ago are == FLAG_NULL <--> (flags_combo_3ago == FLAG_NULL)
and
the input states registered 2 "relevant instants" ago are == FLAG_CROUCH <--> (flags_combo_2ago == FLAG_CROUCH)
and
the input states registered 1 "relevant instants" ago are == FLAG_NULL <--> (flags_combo_1ago == FLAG_NULL)
and
the current input states are == FLAG_FORWARD <--> (flags_combo_now == FLAG_FORWARD)
)then
performs our combo <--> playCustomAnimMove("our_combo_anim_name", 2, 2);
That is, in DoomScript:
Code:
if (( flags_combo_4ago == FLAG_CROUCH ) //crouch
&& ( flags_combo_3ago == FLAG_NULL ) //nothing
&& ( flags_combo_2ago == FLAG_CROUCH ) //crouch
&& ( flags_combo_1ago == FLAG_NULL ) //nothing
&& ( flags_combo_now == FLAG_FORWARD ) ) { //forward
sys.println("combo1");
playCustomAnimMove("ruinblade_combo_1", 2, 2);
}
This is strictly correct, but we can improve it and do much more with this combo system...
//--------------------------------------------------------------------------------
//Designing combos is an art...
//--------------------------------------------------------------------------------
If you understood everything as far as here, you can go on reading.
Now we know that (flags_combo_1ago == FLAG_CROUCH) means that 1 "relevant instant" ago, only CROUCH was pressed
But remember that (flags_combo_1ago & FLAG_CROUCH) means that 1 "relevant instant" ago, at least CROUCH was pressed
Back to out example...
The problem with the previous solution is that it's too rigid: we have to be careful to do not press FORWARD until we've released FLAG_CROUCH again.
Since all this has to be executed very quickly, this could not always happen (try to believe).
That's why the following code is better:
Quote
if (( flags_combo_4ago == FLAG_CROUCH )
&& ( flags_combo_3ago == FLAG_NULL )
&& ( flags_combo_2ago == FLAG_CROUCH )
&& (( flags_combo_1ago == FLAG_NULL ) || (( flags_combo_1ago & FLAG_CROUCH ) && ( flags_combo_1ago & FLAG_FORWARD )) )
&& ( flags_combo_now == FLAG_FORWARD ) ) {
sys.println("combo1");
playCustomAnimMove("ruinblade_combo_1", 2, 2);
}
In fact, it also allows that both CROUCH and FORWARD were pressed 1 "relevant instant" ago.
A lot more complex combos can be done, even if limited to 7 "relevant instants" (but can be increased if we need it).
See the file for more examples.
Also, dodge and dash are now checked this way inside the same function.
No more 2 extra threads running.
//--------------------------------------------------------------------------------
//Ruinblade script rewritten
//--------------------------------------------------------------------------------
As I said at the beginning, now every attack really hit enemies that touch our sword (also more than one).
This means animations become really important, because it only depends on them how useful an attack is.
That's why I've rewritten the ruinblade script allowing us to enter in the "cycle" of animation from different points. That is, when we start attacking, instead of playng always the same animation as first one, now it depends:
- If we are pressing the strafe right button, the first animation will be the attack from right to left.
- If we are pressing the strafe left button, the first animation will be the attack from left to right.
- Otherwise the first animation will be the the old one.
It is very intuitive and the player feels to have more control over what is happening. And of course more strategy is needed.
For example if we have a monster to our right, we can simply hold right before attacking and what we get is that the best animation for this situation is played.
//--------------------------------------------------------------------------------
//Conclusions
//--------------------------------------------------------------------------------
In conclusion, you only need to edit player.def and player.script
- In player.def you can add animations and start/stop melee attacks
- In player.script you can edit check_inputs() to define new combos and start their animations.
I've added, as a test, 4 combos checks for the ruinblade. They only use this system and nothing more.
You can look at/edit them in void player::check_inputs():
1) crouch - crouch - fw //damage x10
2) bw - fw - firesec //damage x2
3) crouch and without releasing it press ( firepri + firesec) //damage x2
4) hold firesec about for a second and release it //damage x2
I've also added this one to the chainsaw (note that it's the same as the first one of the ruinblade, but this is not a problem)
1) crouch - crouch - fw //damage x100
//--------------------------------------------------------------------------------
//Dynamic spread
//--------------------------------------------------------------------------------
Scripted only solution.
Spread is calculated before firing the in "Fire" weapon state based on player speed and posture.
Code:
spread = 5 + sys.vecLength(mypl.getLinearVelocity()) / 30 ; //spread based on player velocity
if(mov_z < 0){ spread = spread/3; }; //spread based on player posture
Dynamic walkspeed:
You can set how much the player speed should be multiplied while firing a specific weapon.
In the weapon .def you can add the key
Code:
"firingWalkSpeedMult" "0.7"
In this example player walk speed will be muliplied by 0.7. That is, player be 30% slower.
//--------------------------------------------------------------------------------
//Enemy Pain reaction Changes
//--------------------------------------------------------------------------------
- The idea:
there are 2 sets of pain anims identified by their name.
1) "pain_zonename" are meant for normal pain (monster stands in place in pain)
2) "highpain_zonename" are meant for high pain (monster falls back/down in pain)
Every damage zone has a current "damage value" that automatically slowly decreases to 0.
When the damage on a zone is greater than the maximum value specified for that zone, the right highpain anim is played and all the damage valuea are reset to 0.
- How to add a new pain animation
Simply add it in the modeldef.
Just make sure overrideLegs is called in order to play it also on legs.
Code:
anim highpain_head models/md5/monsters/vagary/chestpain.md5anim { //this is for head only
frame 1 call overrideLegs //<---!
frame 1 sound_voice
}
NOTE: overrideLegs is not called for maggots, fat and running zombies because their pain anims make them to walk. There's a fix for this in their AIs that force idle anim on legs, but are just exceptions.
In case of missing pain anim for a particular zone:
- standard pain: default anim is "pain"
- high pain: default anim is "highpain" (if even "highpain" is not present, "pain" is played)
- How AIs works
Main changes are in Torso_Pain(), where timeouts and states are set based on the values of boolean flags like AI_HIGHPAIN, AI_COMBOPAIN, AI_MELEEPAIN.
Those timeouts allow check_attacks() to choose only certain type of attacks (usually dodge) for a while after a pain animation.
If AI_HIGHPAIN is true, the monster is set in a state called state_HighPain() that wait for the pain anim to end. This will allow monsters to fall/down back with long animations without the risk that the anim could be interrupted by other attack anims.
- Define values for each monster
example for head zone:
"highpain_threshold head" "180" //180 damage points is the threshold for head zone
"highpain_resettime head" "12" //it takes 12 seconds to go from 180 to 0.
- Minimum time between pain anim
Every monster inherits from monster_default the following keys:
Code:
"pain_threshold" "1" //play pain anims if damaged more than 1hp (that is, always)
"pain_delay" "1" //minimum time between 2 pain anims and pain sounds.
Note that those values are NOT used if pain is inflicted by a melee damage (the ones with the key "melee" "1") because monsters should be always ready to react to combo or simple sword attacks.
What is really the minimum time between the beginning of 2 pain anims is the value
Code:
nextpain = sys.getTime() + 0.1;
that is set in Torso_Pain() animstate.
It is usually 0.1 seconds. But in the case of archvile, hellknight and vagary this value is much higher and is checked also in other animstates in order to make them harder to fight.
- Force pain type with combo
You can call the following function from the combo animation itself
Code:
void comboForceHighPain();
void comboAllowHighPain();
void comboDenyHighPain();
example:
Code:
anim ruinblade_combo_1 todo.md5anim{ //to do: create a proper anim
frame 1 sound_body player_sword_fire
frame 2 object_call startWeaponAutoMeleeX1 //start attack 1
frame 2 object_call comboDenyHighPain//every actor hit will choose standard pain anims
frame 9 object_call stopWeaponAutoMeleeAny //end attack 1
frame 10 object_call startWeaponAutoMeleeX2 //start attack 2
frame 10 object_call comboForceHighPain //every actor hit will choose highpain anims
frame 20 object_call stopWeaponAutoMeleeAny //end attack 2
}
No need to reset damage multiplier or pain anim type because they work only while a combo is performed.

148
documents/grabber notes.txt Normal file
View file

@ -0,0 +1,148 @@
This was the list I used to port the grabber code from D3 ROE to Vanilla Doom3 -Rev
look up and add the following stuff:
grab
x Game_local.h
x AFEntity.cpp
x Entity.cpp
x Entity.h
X Weapon.cpp
X weapon.h
X SysCvar.cpp
X SysCvar.h
X AI_events.cpp
drag
X Weapon.cpp
X SysCvar.cpp
X SysCvar.h
monster_damage
X Moveable.cpp
attacker
x Moveable.cpp
X Moveable.h
g_moveableDamageScale
X SysCvar.h
X syscvar.cpp
x Moveable.cpp
IsStable
X Moveable.h
x movalbe.cpp
CatchProjectile
X Projectile.cpp *****1162 OTHER STUFF WAS ADDED THAT COULD BE RELATED.
x Projectile.h
StartBurning
X Moveable.cpp
X Moveable.h
StopBurning
X Moveable.cpp
X Moveable.h
SetThrown
X AFEntity.cpp
X AFEntity.h
wasThrown
X AFEntity.cpp
X AFEntity.h
SetAttacker
X Moveable.cpp
X Moveable.h
SetStability
X Moveable.cpp
X Moveable.h
GetProjectileState
X Projectile.cpp
x Projectile.h
IsStable
X movables.cpp
X and h.
monsterDamage
X movables.cpp
X movables.h
SetEnemy
X Projectile.h
x projectile.cpp
attacker
X movables.cpp
X movables.h
to bypass the slow errors, we replaced those parts with gamelocal.time instead of gamelocal.slow.time in the grabber cpp.
The time group stuff and anything with warp in it was also commented out of the grabber.cpp and grabber.h
The following stuff might be related, but most likely isn't.
slow
Actor.cpp
AFEntity.cpp
AI.cpp
Fx.cpp
Class.cpp
Event.cpp
SysCvar.cpp
SysCvar.h
Game_local.cpp
Game_local.h
Game_network.cpp
Item.cpp
Mover.cpp
Physics_AF.h
Physics_Player.cpp
Player.cpp
Player.h
PlayerView.cpp
PlayerView.h
attacker
Actor.cpp
Actor.h
AfEntity.cpp
AfEntity.h
AI.cpp
AI.h
BrittleFracture.cpp
BrittleFracture.h
Entity.h
Game_local.cpp
Game_local.h
Light.h
Light.cpp
Misc.cpp
Misc.h
Mover.cpp
Mover.h
Player.cpp
Player.h
Projectile.cpp
Projectile.h
Script_Thread.h
SecurityCamera.cpp
SecurityCamera.h
CreateProjectile
x PROJECTILE.CPP
projectile.h
x WEAPON.CPP
LaunchProjectile
AI.CPP
AI.H
AI_EVENTS.CPP
ANIM_BLEND.CPP
x PROJECTILE.H
X WEAPON.H
SetGravity
Projectile.h
Projectile.cpp
Player.cpp
Physics_StaticMulti.h
Physics_StaticMulti.cpp
Physics_Static.h
Physics_Static.cpp
Physics_Base.h
Physics_Base.cpp
Physics_Actor.h
Physics_Actor.CPP
Physics.h
Moveable.cpp
Item.cpp
BrittleFracture.cpp
AI.cpp
AFEntity.cpp
AF.cpp

View file

@ -0,0 +1,76 @@
List of CVARS:
r_HDR_enableDebugMode
r_HDR_debugTextureIndex
r_HDR_postProcess
r_HDR_middleGray
r_HDR_brightPassThreshold
r_HDR_brightPassOffset
r_HDR_min_luminance
r_HDR_max_luminance
r_HDR_eyeAdjustmentDelay
r_HDR_colorCurveBias
r_HDR_maxColorIntensity
r_HDR_bloomIntensity
r_HDR_enableDebugMode (Integer)
default value 0
Shows all the textures generated for HDR postprocess.
1: Shows all textures (Endecoded), namely: 64x Downscaled scene image, 64x64 luminance texture (stores averaged scene luminance), 4x4 luminance texture, 1x1 adapted luminance texture, bloom result texture.
2: Decodes and shows all textures
r_HDR_debugTextureIndex (Integer)
default value 0
Show intermediate textures used for HDR postprocess
0: Off.
1: scene Image(64x Scaled down)
2: Result of first bloom pass.
3: Result of second bloom pass.
r_HDR_postProcess (Bool)
default value 1
Activates HDR tone mapping and bloom
r_HDR_brightPassThreshold (Float)
default value 5.0
brightness threshold for Bright-pass. E.g. color intensities beyond 5.0 will be bloomed and hence only very bright areas would qualify for blooming.
r_HDR_brightPassOffset (Float)
default value 10.0
Brightness offset for bright pass. E.g. Color intensities beyond r_HDR_brightPassThreshold will receive a nice gradually faded bloom from dark to bright giving color intensity of 10.0 the brightest bloom. To get a good understanding, set r_debugTextureIndex to 2 or 3 and then change this value to visualize the bloom image.
r_HDR_middleGray (Float)
default value 0.08
Middle gray value for overall scene ( Range 0 - 1) . Higher the value, brighter the scene.
r_HDR_min_luminance (Float)
default value 0.06
Measured luminance of the scene is restricted to this value to control how bright a lit area should get when standing in complete dark areas.
r_HDR_max_luminance (Float)
default value 0.22
Luminance is restricted to this value to control darkness when in super-bright areas. E.g. If you are looking at a very bright sky everything else around will get darker. This variable lets you control how much darker the surrounding should get when looking at full bright areas.
r_HDR_eyeAdjustmentDelay (Float)
default value 1.6
Total time in second taken to adjust eye exposure.
r_HDR_colorCurveBias (Float)
default value 0.3
Applies an exponential S-Shaped color curve to final pass (range 0 to 1), E.g. 1.0 = color curve fully applied , 0.0 = No color curve
See following 2d graph to grasp the working of color-curve bias.
r_HDR_maxColorIntensity (Float)
default value 3.0
Adjusting this value will cause color burnout of high dynamic range values going beyond 255 in a controllable fashion (range 0.0 - 256.0). This step is performed while bringing the HDR values into displayable range (0-255), also known as tone mapping.
Higher values reduces the contrast, lower values increases the contrast.
See Example Images:
r_HDR_bloomIntensity (Float)
default value 1.0
Adjusts the Bloom intensity. This CVAR is not being used yet.

View file

@ -0,0 +1,311 @@
RUINER CHANGELOG by Ivan_the_B
/***********************************************************************
NEW/EDITED FILES
***********************************************************************/
------------------------------------------------
SUBJECT -> FILENAME sdk | game
------------------------------------------------
headshot system -> Weapon.cpp, Actor.cpp | damage.def, ai_monster_base.script
weapon HS enabled -> weapon_onslaught.def, weapon_ruinblade.def
monsters no HS -> monster_spirits.def, monster_demon_imp_nightmare.def
setOwner proj. fix -> Entity.cpp, Projectile.cpp and .h
dynamic friends -> AI.cpp | ai_monster_base.script
music volume system -> Script_Thread.cpp and .h, SysCvar.cpp and h | ff_musics.script, ai_player.script, speaker_music.def
load default cfg -> Game_local.cpp, SysCvar.cpp and h
new events -> Entity.cpp and .h, Player.cpp and .h, Weapon.cpp and .h, AI.cpp and .h, AI_events.cpp, Anim_Blend.cpp, Anim.h | doom_events.script
friendly damage -> Player.cpp and .h
maledict -> aas.def, pak666_maledict.pk4
fake proj. monster -> monster_projectile.def, ai_fake.script
melee for weapons -> Weapon.cpp and .h, Anim_Blend.cpp, Anim.h
combo system -> ai_player.script
full body player anim -> Player.cpp and .h, Physics_Player.cpp and .h | ai_player.script, weapon_base.script
pain system -> AI.cpp and .h, Actor.cpp and h | ai_monster_base.script, monster_default.def, all the script and def that uses it
dynamic spread -> weapon_advocate.script, weapon_onslaught.script
dynamic walkspeed -> Weapon.cpp and .h, Player.cpp
wall dodge -> ai_player.script
cursor object -> Player.cpp and .h ( code moved from Weapon.cpp and .h ), PlayerCursor.cpp
arrows -> Moveable.cpp and .h, Projectile.cpp and .h | arrow.def
secondary attack sys -> Weapon.cpp and .h, Player.cpp and .h | ai_player.script, weapon_base.script
kicks -> Player.cpp and .h, Anim_Blend.cpp, Anim.h | kicks.def
/***********************************************************************
New Entities (excluding monsters,projectiles...)
***********************************************************************/
music_speaker -> Speaker for musics
music_stop -> Trigger that calls the Script Function stop_music()
target_maledict_land -> Target for maledict_flying. Place it where it should teleport back after walking.
target_maledict_takeoff -> Target for maledict_flying. Place it where it should land.
moveable_arrow -> Spawned by the game for arrows projectiles. It automatically unbinds after a while, wait few secs, is removed.
/***********************************************************************
New Scriptevents
***********************************************************************/
------------------------------------------------
All entities
------------------------------------------------
scriptEvent float getEntityHealth();
scriptEvent void setEntityHealth( float health );
scriptEvent string getGuiParm(float guiNum, string key);
scriptEvent float getGuiParmFloat(float guiNum, string key);
scriptEvent void guiNamedEvent(float guiNum, string event);
scriptEvent entity fireProjectile( string projDefName , vector firePos, vector fireAng );
scriptEvent entity fireProjAtTarget( string projDefName , vector firePos, entity aimAtEnt );
scriptEvent entity getClosestTargetTypePrefix( string typePrefix, string ignoreType );
scriptEvent entity getRandomTargetTypePrefix( string typePrefix, string ignoreType );
------------------------------------------------
System events (called via 'sys.')
------------------------------------------------
scriptEvent float getShaderVolume( string sound );
scriptEvent vector rotateVector( vector vec, vector ang );
------------------------------------------------
Animated entities
------------------------------------------------
scriptEvent entity fireProjectileFromJoint( string projDefName, float jointnum, vector fireAng );
scriptEvent entity fireProjAtTargetFromJoint( string projDefName, float jointnum, entity aimAtEnt );
------------------------------------------------
players
------------------------------------------------
scriptEvent void setArmor(float newArmor);
scriptEvent float getArmor();
scriptEvent void addProjectilesFired(float num);
scriptEvent void addProjectileHits(float num);
scriptEvent void setAnimMoveOn();
scriptEvent void setAnimMoveOff();
scriptEvent void setGravityInAnimMove(float mult);
scriptEvent void forceHighPain(float mode); //-1 disabled, 0 allowed, 1 forced
scriptEvent void forceUpdateNpcStatus();
scriptEvent void startKick(string meleeDefName, float dmgMult);
scriptEvent void stopKick();
------------------------------------------------
Weapons
------------------------------------------------
scriptEvent void startAutoMelee( float dmgMult );
scriptEvent void stopAutoMelee();
scriptEvent void setWeaponMode( float value );
scriptEvent float getWeaponMode();
scriptEvent void launchProjectiles( float num_projectiles, float spread, float fuseOffset, float launchPower, float dmgPower, float projtype ); //projtype added
scriptEvent entity createProjectile( float projtype ); //projtype added
------------------------------------------------
idAI
------------------------------------------------
scriptEvent void moveToPositionDirect( vector pos );
scriptEvent void avoidObstacles( float avoid );
scriptEvent void triggerFX( string joint, string fx );
scriptEvent entity startEmitter( string name, string joint, string particle );
scriptEvent entity getEmitter( string name );
scriptEvent void stopEmitter( string name );
------------------------------------------------
idAI_Bot
------------------------------------------------
scriptEvent float selectBotWeapon( float weaponNum );
scriptEvent float selectAnotherWeapon( float idealLevel, float minLevel );
scriptEvent float getCurrentBotWeapon();
scriptEvent float getBotWeaponNumByName( string weaponName );
scriptEvent entity fireWeapon();
scriptEvent void reloadWeapon();
scriptEvent float checkReloadTolerance();
scriptEvent float getAmmoInClip();
scriptEvent float getClipSize();
scriptEvent string getIdleAnim();
scriptEvent string getReloadAnim();
scriptEvent string getFireAnim();
scriptEvent float canHitEnemyFromCurrentWeapon();
scriptEvent float canFireToEnemyNoSelfDamage(float requireVisible);
scriptEvent float canHitEnemyFromFireAnim(float weaponToTest);
scriptEvent float lostTimeMoreThan(float time);
scriptEvent float weaponChangedMoreThan(float time);
scriptEvent void playAnimOnWeapon( string animname );
scriptEvent float tryLockNode(entity node);
scriptEvent void releaseCurrentNode();
scriptEvent entity findEnemyAIorPL( float onlyInFov );
------------------------------------------------
idBotNode
------------------------------------------------
scriptEvent float evaluateConditions();
scriptEvent entity getNextUsableNode( entity botEntity );
scriptEvent float canBeUsedBy( entity botEntity );
scriptEvent void reached();
/***********************************************************************
New Global Script Functions
***********************************************************************/
void start_music(entity m_speaker);
void set_fadeout_time(float new_fadeout_time); //no need to use this
void stop_music();
/***********************************************************************
New Player Script Functions meant to be called by player animations
***********************************************************************/
void enableGravityInAnimMoveX1();
void enableGravityInAnimMoveX05();
void disableGravityInAnimMoveAny();
/***********************************************************************
New Keys
***********************************************************************/
------------------------------------------------
Entity type -> "New_Key" "default"
------------------------------------------------
damage def -> "check_headshot" "0"
damage def -> "damageSpirits" "0"
damage def -> "melee" "0"
damage def -> "ignore_friends" "0" //ignore player team (0)
damage def -> "playerDamageScale" "1"
actor -> "headshot_disabled" "0"
actor -> "highpain_threshold zonename" "0"
actor -> "highpain_resettime zonename" "0"
AI -> "staticDeath" "0" //for Icon Of Sin
weapon -> "melee_tracerWidth" "0"
weapon -> "firingWalkSpeedMult" "1"
projectile -> "isArrow" "0"
projectile -> "getHitEntity" "0" //for Icon Of Sin's fireball
damage def (kicks) -> "kick_tracerWidth" "1"
damage def (kicks) -> "kick_distance" "0"
damage def (kicks) -> "from_joint" ""
damage def (kicks) -> "to_joint" ""
/***********************************************************************
New Framecommands
***********************************************************************/
------------------------------------------------
idAI_Bot
------------------------------------------------
fire_weapon
------------------------------------------------
player
------------------------------------------------
comboForceHighPain
comboAllowHighPain
comboDenyHighPain
startAutoMelee [interger_positive_value]
stopAutoMelee
startKick [damage_name] [interger_positive_value]
stopKick
weapon_call [function_name]
/***********************************************************************
What we can do from player anims - quick overview and examples
***********************************************************************/
//-- gravity --
//note1: gravity is already set in player script when the combo is called
//note2: no need to reset it back to 1 at the end of the anim
frame 1 object_call disableGravityInAnimMoveAny //disable gravity
frame 1 object_call enableGravityInAnimMoveX05 //gravity 0.5
frame 1 object_call enableGravityInAnimMoveX1 //default gravity
//-- force high pain --
//note1: default is allow (like standard attacks)
//note2: no need to reset it back to allow at the end of the anim
frame 1 comboForceHighPain
frame 1 comboAllowHighPain
frame 1 comboDenyHighPain
//-- start/stop attacks --
//note1: damage multiplier is a positive integer number
//note2: you can start it many times in the same anim
frame 1 startAutoMelee 1
frame 1 startAutoMelee 100 //any positive integer number!
frame 1 stopAutoMelee
//-- start/stop kicks --
//note1: damage multiplier is a positive integer number
//note2: you can start it many times in the same anim
//note3: you can use different def_damage in the same anim
frame 1 startKick damage_rightPunch 1
frame 1 startKick damage_leftPunch 100 //any positive integer number!
frame 1 stopKick
//-- weapons utilites --
frame 1 weapon_call fromPlayerAnimTest //call the "fromPlayerAnimTest" function on weapon scriptobject
/***********************************************************************
New Cvars
***********************************************************************/
------------------------------------------------
Cvar name -> Description
------------------------------------------------
s_music_volume -> In-game music volume. (-10 = disabled )
ruiner_bind_run_once -> Rebind all controls once for Ruiner.
/***********************************************************************
MALEDICT SCRIPT FUNCTIONS, call with .callFunction("f_name");
***********************************************************************/
------------------------------------------------
FLYING MALEDICT
------------------------------------------------
void enable_phases();
void disable_phases();
void enable_attack_bigasteroid();
void disable_attack_bigasteroid();
void request_landing();
void request_teleport_closer();
void request_teleport_spec_entity();
void enable_waiting();
void disable_waiting();
------------------------------------------------
WALKING MALEDICT
------------------------------------------------
void enable_phases();
void disable_phases();
void enable_attack_multiast();
void disable_attack_multiast();
void request_attack_multiast();
void request_takeoff();

View file

@ -0,0 +1,75 @@
Install:
- delete the old "maledict" mod folder
- extract the zip file in the doom3 folder
- run the mod with the bat file... or load it as mod and load the "maledict" map
How to import in Ruiner:
- simply copy the file "maledict.pk4" in your mod folder.
- in doom_main.script add, somewhere after the declaration of "ai_monster_base.script" (where you declared the Guardian stuff is ok):
Code:
#include "script/ai_fake.script"
#include "script/ai_monster_boss_maledict.script"
#include "script/ai_monster_boss_maledict_walking.script"
#include "script/projectile_maledict.script"
- ok, what we've done should generate a problem with my old guardian script
To solve this you have to open ai_monster_boss_guardian.script, go to the end of file and delete:
Code:
/***********************************************************************
ai_fake
***********************************************************************/
object ai_fake : monster_base {
// States
void state_Begin();
void state_Idle();
void init();
};
/*
=====================
ai_fake::init
=====================
*/
void ai_fake::init() {
ignoreDamage();
becomeNonSolid();
setState( "state_Begin" );
}
void ai_fake::state_Begin() {
setState( "state_Idle" );
}
void ai_fake::state_Idle() {;}
- done.
How it works:
I suggest to copy in you map folder also the testmap included in the zip, so that you can test if everything is ok and look at what I've done in it.
- The flying and the walking monster need to be both palced in the map and - as you can see in the entity inspector- they have an extra key: you need to set on each of them the name of the other one.
- The flying one has a lot of targets red and green.
The green ones are the points where he can teleport from ground to air. (the closer one will be chosen)
The red ones are the points where he can teleport from air to ground. (the closer one will be chosen)
If you don't set any target, he will simply teleport up/down where he previously was.
- The energy is shared, and you can set it,as usual, in the editor on the flying one. The energy of the walking one is ignored.
- The monster always starts with the flying one, that only supports the "hide" key.
The walking one is automatically hidden at the beginning of the map and you don't need to set any key on it.
- you have to place an extra wall of monster clip, like in the testmap, to stop him from clip in the wall while preforming his flying attacks.
Ok, I know that some projectiles could need some changes to fit the player speed and some variables could be edited based on the size of the place. Let me know, when you need it, what changes are necessary.

View file

@ -0,0 +1,51 @@
trigger enemy to spawn with no fx
trigger once->enemy. set teleport 0
To have a teleport fx, set teleport to 2.
DOOR DIRECTIONS:
down movdir -2
up movedir -1
left 180
right 0
lip -10
door to lock by default. set locked 1.
entity to unlock doors: target_lock if a door is already locked, then set locked 0
door sounds:
snd_close hh_door_movement_3s
snd_open hh_door_movement_3s
guardian floor explosions
func_explosion
cinematic 1
hide 1
s_shader hh_rockslide_01
start_off 1
example script for music
void wilderness_out()
{
stop_music(); //$music_wilderness.fadeSound(SND_CHANNEL_ANY, -60, 9);
start_music($music_cumha); //$music_cumha.activate($player1);
}
Entity set up. This is called via the script to start or stop.
name music_nothing
class name music_speaker
s_shader nothing_music
s_shader for sin level music catacombs2_music
s_shader for pinion level repression_music
s_shader for pinion boss nothing_music
s_shader for sin boss nothing_music

View file

@ -0,0 +1,56 @@
Greetings and welcome to a different kind of tutorial. When you look at the main site for TheRuiner mod, you will notice we have many people listed in thanks for helping us. This is one of the greatest things about mod developing and one of its main strengths, helping other amature developers out.
When we started to plan out Ruiner, we wanted to make sure the mod was possible without the need of a programmer for putting in the main game features. We scoured the community, searched through message boards and asked questions when needed. In the end we have been able to put in all the major features we wanted without a real programmer.
Below is a list of topics found on the popular www.doom3world.org modding forums. With the info from each of these topics, one can easily create a thirdperson Doom3 complete with crosshairs, and hud. People reading this from outside the Doom3 scene might wonder why this information is important. Its interest is related to the fact that when you try to set Doom3 in thirdperson, the hud, camera settings, and cross aren't there by default. You need to do some SDK, script and Def related work to get it working.
Please remember, this is written for a Doom3 modder who is already familar with the basics of Doom3 modding and working with the SDK, scripts and Def files. Some information written below will sound like greek to anybody else. There are many places to find info on getting started with Doom3 modding basics.
How to enable the Thirdperson hud:
http://www.doom3world.org/phpbb2/viewtopic.php?f=56&t=19964&hilit=thirdperson+hud
Check the very last post by port666 for how to do it. Just remember that if done this way, Many hud effects, such as damage effects, won't be seen.
Alternate way to enable the Thirdperson hud:
http://www.doom3world.org/phpbb2/viewtopic.php?f=67&t=16624
Look halfway through the thread, you will see a post by RPRaiden. This explains a more complicated way to enable the hud.
AFter enabling the Hud, you will notice something is wrong with the crosshairs. They are very inacurate. In order to bypass this hurdle, we need to create a new cross hair code.
Tutorial by Deavile is found here:
http://www.doom3world.org/phpbb2/viewtopic.php?f=56&t=16783&view=next
Special notes about this tutorial:
When compiling, don't forget to include the files in your build or it won't work.
Almost at the very bottom of the thread is a post by Deus231. In his post he has a little code that is useful.
What his code does is make the cross hair always move around when you move the mouse. If you don't add this code in, the crosshair doesn't update its position after the player attacks.
Once the new crosshair is implanted, the old one needs to be removed. After doing the cross hair tutorial, you might wind up with two cross hairs on the screen, one old and the other the new more acurate one.
To remove the old cursor, open up the gui file "cursor.gui" in the guis folder. Comment out the "windowDef crosshairParent" section and your good to go.
Another note on the crosshairs are physical projectiles, such as the plasma gun's plasma balls, and rockets from the rocket launcher. If "launchfrombarrel" is set to "1" in a weapon's projectile def, the projectile will not be acurate with the crosshair. It will fire from the weapon's barrel when not moving. Setting launchfrombarrel to 0 will have it launch from the default position, player's eyes, and be acurate.
At the moment, I do not have the solution to fix this bug.
The final part of this tutorial list belongs to camera settings. You can set the default height, range and angle of the thirdperson camera in doom3.
This can be done in the sdk, and in the Player.def file. Doing it both ways is the most effective way to make sure it always works and is never overwritten. The most important thing to set in the SDK is pm_thirdperson to 1 instead of 0 in the SysCvar.cpp file. This will make the mod start off in thirdperson by default. All other camera settings are set in there as well.
In the Player.def file, you can add the console commands to change the default camera position without use of the sdk. Setting it in the sdk is optional.
To add in the camera info, go in the Player.def file and under entityDef player_base. As you look through the player_base, you see some of the default settings and information on what weapons the player carries, ammo, etc. Halfway through it, are many settings with the "pm_" prefix such as pm_jumpheight.
Now add in:
////START thirdpersoncamsettings
"pm_thirdperson" "1" //enables thirdperson view
"pm_thirdpersonheight" "0" //Sets the vertical position of the camera. Use negative numbers to move it down even further
"pm_thirdpersonangle" "0" //rotates the camera around the player from 0-360
"pm_thirdpersonrange" "100" //sets how far away the camera is from the player
"pm_thirdpersonclip" "1" //Sets whether or not the camera can clip through brushes. if set to "0", it will move through brushes.
////END thirdpersoncamsettings
Set them to whatever you feel is best for your mod. If the angle is changed to any amount besides 0, then freelooking with the mouse no longer works. If the thirdpersonclip is set to 0, the camera will clip through walls, and objects in the map. This leads to a wealth of performance and visual problems.

View file

@ -0,0 +1,338 @@
setting up thirdperson view in doom3
doom3worlds for source:
http://www.doom3world.org/phpbb2/viewtopic.php?t=16680
this is for third person cross hair. Remember when adding the new playercursor.cpp and h to put them in your solution for building or it will not compile
After words you will need to remove the regular cross hair.
To remove the regular cross hair:
go to the player.cpp file and search for crosshair. there is only one function. void out the section of code and your good to go.
At the end of the crosshair tutorial you will notice for the weapon.cpp file it wants a material path.
this is actually the path to the texture itself. you do not have to put a .tga extentsion though. the texture needs to be transparent though.
thats it. Make sure the tga your using is transparent. You can control the color and alpha of it in the playercursor.cpp you create in the tutorial.
////////////////////////////////////////////////////////////////////////////////
///Third person cross hair tutorial by Deavile Aug 05, 2006
///////////////////////////////////////////////////////////////////////////////
This tutorial will teach you how to create an accurate 3rd Person cross hair. The cross hair is actually a 2d sprite placed in the game world at a location that will indicate where the player's weapon will strike. The cross hair will work with any camera height and distance, and even works in first person.
Part one: The PlayerCursor class
To create our new cross hair you will need to implement a new class in the D3 SDK. This class will determine where the cross hair should be placed in the game world and will spawn a sprite at that location.
Step One: PlayerCursor.h
Create a new .h file in the GAME folder named PlayerCursor. The variables and functions defined with in PlayerCursor.h should be the same as the code below.
Code:
#ifndef __PLAYERCURSOR_H__
#define __PLAYERCURSOR_H__
/*
Created on 4/19/06 by Paul Reed
Draws a cross hair sprite 5 feet from the view origin along a line leading to where
the player's weapon is pointing
*/
class idPlayerCursor {
public:
idPlayerCursor();
~idPlayerCursor();
void Draw( const idVec3 &origin,const idMat3 &axis,const char *material );
public:
renderEntity_t renderEnt;
qhandle_t cursorHandle;
bool created;
public:
void FreeCursor( void );
bool CreateCursor( idPlayer* player , const idVec3 &origin, const idMat3 &axis,const char *material);
void UpdateCursor( idPlayer* player ,const idVec3 &origin, const idMat3 &axis);
};
#endif /* !_PLAYERCURSOR_H_ */
Step Two:PlayerCursor.cpp Basics
Create a new .cpp file in the GAME folder named PlayerCursor and include the following lines of code at the top of the file.
Code:
#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
#include "PlayerCursor.h"
Next you will want to create the constructor and deconstructor functions. The constructor function should look like this:
Code:
/*
===============
idPlayerCursor::idPlayerCursor
===============
*/
idPlayerCursor::idPlayerCursor() {
cursorHandle = -1;
created = false;
}
And the deconstructor like this:
Code:
/*
===============
idPlayerCursor::~idPlayerCursor
===============
*/
idPlayerCursor::~idPlayerCursor() {
FreeCursor();
}
The Deconstructor makes a call to FreeCursor, which frees up the renderEntity (the image of the sprite) , sets the cursorHandle (which keeps track of our renderEntity) to -1, and sets the bool created to false.
Code:
/*
===============
idPlayerCursor::FreeCursor
===============
Post: tells the game render world to free the cross hair entity, sets the cursor
handle to -1 and sets created to false
*/
void idPlayerCursor::FreeCursor( void ) {
if ( cursorHandle != - 1 ) {
gameRenderWorld->FreeEntityDef( cursorHandle );
cursorHandle = -1;
created = false;
}
}
Step Three:PlayerCursor.cpp The Draw function
This critical function does most of the work of the PlayerCursor class, and is called by an outside class to create the cross hair. The first two parameters are the location and facing of the player, while the third is the name of the material to be used for the cross hair.
Code:
/*
===============
idPlayerCursor::Draw
===============
*/
void idPlayerCursor::Draw( const idVec3 &origin, const idMat3 &axis,const char *material) {
The first step is to trace a point from the player's position (variable origin) along the passed in axis(variable axis). The point where the trace stops is where the weapon is aiming.
Code:
idPlayer *localPlayer = gameLocal.GetLocalPlayer();
trace_t tr;
float distance = 60;
float length;
//detemine the point at which the weapon is aiming
idAngles angle = axis.ToAngles();
idVec3 endPos =(origin + (angle.ToForward() * 120000.0f));
gameLocal.clip.TracePoint(tr,origin,endPos,MASK_SHOT_RENDERMODEL,localPlayer);
endPos = tr.endpos;
The next step is to find the distance between the camera (variables cameraOrigin, and cameraAxis), and the point where the weapon is aiming. The cross hair position is found by using the two vectors (the camera's position and the point where the player is aiming), and interpolating a point 60 inches (defined by variable distance) from the camera. If you like you may change the distance to any number of inches you like. Note that if you go to far the cross hair's sprite will be hidden by the player's model.
Code:
//find the distance from the camera to the point at which the weapon is aiming
idMat3 cameraAxis = localPlayer->GetRenderView()->viewaxis;
idVec3 cameraOrigin = localPlayer->GetRenderView()->vieworg;
idVec3 vectorLength = endPos - cameraOrigin;
length = vectorLength.Length();
length = distance/length;
//linearly interpolate 5 feet between the camera position and the point at which the weapon is aiming
endPos.Lerp(cameraOrigin,endPos,length);
Finally we create a cursor if we haven't already done so, and if we have then we update it's position to the point we determined. Make sure to pass in the camera's axis (variable cameraAxis) so that the 2d sprite is facing the right direction.
Code:
if ( !CreateCursor(localPlayer, endPos, cameraAxis,material )) {
UpdateCursor(localPlayer, endPos, cameraAxis);
}
}
Step Four:PlayerCursor.cpp The CreateCursor function
The CreateCursor function's job is to create a renderEntity that the cross hair will be displayed on. The renderEntity will use a sprite as a model and will use the passed in material as it's texture. You can change the color parameters to whatever you want, as well as the size parameters, though I find 8 by 8 units to be about right.
Code:
/*
===============
idPlayerCursor::CreateCursor
===============
*/
bool idPlayerCursor::CreateCursor( idPlayer *player, const idVec3 &origin, const idMat3 &axis, const char *material ) {
const char *mtr = material;
int out = cursorHandle;
if ( out >= 0 ) {
return false;
}
FreeCursor();
memset( &renderEnt, 0, sizeof( renderEnt ) );
renderEnt.origin = origin;
renderEnt.axis = axis;
renderEnt.shaderParms[ SHADERPARM_RED ] = 1.0f;
renderEnt.shaderParms[ SHADERPARM_GREEN ] = 1.0f;
renderEnt.shaderParms[ SHADERPARM_BLUE ] = 1.0f;
renderEnt.shaderParms[ SHADERPARM_ALPHA ] = 0.5f;
renderEnt.shaderParms[ SHADERPARM_SPRITE_WIDTH ] = 6.0f;
renderEnt.shaderParms[ SHADERPARM_SPRITE_HEIGHT ] = 6.0f;
renderEnt.hModel = renderModelManager->FindModel( "_sprite" );
renderEnt.callback = NULL;
renderEnt.numJoints = 0;
renderEnt.joints = NULL;
renderEnt.customSkin = 0;
renderEnt.noShadow = true;
renderEnt.noSelfShadow = true;
renderEnt.customShader = declManager->FindMaterial( mtr );
renderEnt.referenceShader = 0;
renderEnt.bounds = renderEnt.hModel->Bounds( &renderEnt );
cursorHandle = gameRenderWorld->AddEntityDef( &renderEnt );
return false;
}
Step Four:PlayerCursor.cpp The CreateCursor function
The final function in PlayerCursor is used to update the position of cross hair to the values passed in.
Code:
/*
===============
idPlayerCursor::UpdateCursor
===============
*/
void idPlayerCursor::UpdateCursor(idPlayer* player, const idVec3 &origin, const idMat3 &axis) {
assert( cursorHandle >= 0 );
renderEnt.origin = origin;
renderEnt.axis = axis;
gameRenderWorld->UpdateEntityDef( cursorHandle, &renderEnt );
}
Note: If your cross hair is a GUI and you want to set a GUI variable (which you may have passed into the draw function) use this code:
Code:
renderEnt.customShader->GlobalGui()->SetStateBool("guiVariableName",yourVariable);
Part Two: Modifying other classes
Step One: gameLocal.h
Now that the PlayerCursor class has been created you need another class to use it, but before that you must add the following line to gameLocal.h around line # 730:
Code:
#include "PlayerCursor.h"
be sure to place it above the line:
Code:
#include "Entity.h"
Step Two:Weapoh.h
Since the point the player aims at is determined in Weapon, the playerCursor class should be defined here. Add a idPlayerCursor variable (either private or public) to Weapon.h.
Code:
idPlayerCursor playerCursor;
Step Three:Weapon.cpp
The final step is the call the playerCursor's draw function inside the idWeapon::PresentWeapon function. Place the following line of code at the very bottom of the function:
Code:
playerCursor.Draw(muzzleOrigin,muzzleAxis,"pathNameToMaterialDefinition/MaterialName");
That should do it, if you did everything right you should now have an accurate 3rd person cross hair!
Part Three: a few quick notes
I deleted the majority of my comments to help keep the tutorial length under control. I encourage everyone who implements this to put their own comments in as they code (or cut and paste ). Comments are damn important and should never be left out or put aside to be done later.
I have not tested the cross hair in multiplayer, and I believe there may be trouble with seeing everyone else's cross hairs. If you implement this and give it an MP test please let me know if it works alright.
Finally a quick thanks. I discovered how to create the cross hair by looking at the playerIcon class; so thanks to whoever at ID wrote the class.
If you have any questions or comments please post them here or IM me. If you discover an error in my post OR in the code please point it out.
Additional notes from Deuss231:
Well, I just finished implementing it and I've gotta say it works great except for one small problem: muzzleOrigin and muzzleAxis don't update unless the weapon is firing. It's easy enough to solve simply by adding:
Code:
muzzleOrigin = playerViewOrigin;
muzzleAxis = playerViewAxis;
Right before the call to playerCursor.Draw in PresentWeapon.
//////////////////////////////////////////////////////////////////////
// Third person hud code. Author, many.
// http://www.doom3world.org/phpbb2/viewtopic.php?t=16624&highlight=enable+hud
//////////////////////////////////////////////////////////////////////
Yeah it's simple, you can do it for SP easier than MP.
You need to edit your Game SDK.
add in GameSys/SysCvar.h
Code:
extern idCVar pm_thirdPersonHud; // New Cvar
add in GameSys/SysCvar.cpp
Code:
// Third Person Hud
idCVar pm_thirdPersonHud( "pm_thirdPersonHud", "1", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_BOOL | CVAR_NOCHEAT, "enables hud in third person mode" );
(They are pretty simple adds, find the pm_thirdPerson in and add it below)
Then open up Player/PlayerView.cpp and find the SingleView class.
In there find this:
Code:
if ( !pm_thirdPerson.GetBool() && !g_skipViewEffects.GetBool() ) {
and change it to
Code:
if ( !pm_thirdPerson.GetBool() && !g_skipViewEffects.GetBool() || pm_thirdPersonHud.GetBool() ) {
I basically searched through the forums and found that answer, so I won't claim that as my own.
////////////////////////////////////////////////////
// Enable thirdperson view and setting by default
///////////////////////////////////////////////////
To have the game in thirdperson from the start:
add the following to the player.def file Under the entity def player_base. Good to add it after the weapons part during the pm section.
// start thirdpersoncamsettings
"pm_thirdperson" "1"
"pm_thirdpersonheight" "10"
"pm_thirdpersonangle" "0"
"pm_thirdpersonrange" "150"
"pm_thirdpersonclip" "1"
// REV END
Change the values to your needs.