86 Commits

Author SHA1 Message Date
Giegue
f035b865e5 Fix Alien Slave beams not clearing upon gib/removal.
Fix env_smoker showing as func_wall.
Fix pev->message field not working on many entities.
Fix monstermaker "soundlist" keyvalue not working.
Add prisoner spawnflag (16) for monstermaker.
Add poison damage to spore grenades.
Increase max entities from 512 to 768.
Increase max spawnpoints from 256 to 384.
2024-01-21 14:46:32 -03:00
Giegue
9f77e10934 - Fix a few possible crashes.
- Fix xenmaker sprites never being removed if their framerate is 0.
- Fix xenmaker sprites never showing if their scale is 0.
- Add trigger_setcvar.
- New "health" keyvalue for monsters/monstermaker for custom health.
2024-01-10 16:05:40 -03:00
Giegue
75596ad87e Fix xenmaker monsters not fading, again. 2023-11-02 16:13:45 -03:00
Giegue
f57c7760f7 Fix xenmaker sprite effects.
Fix xenmaker monsters not fading after death.
2023-10-21 14:01:48 -03:00
Giegue
8ed6c4eb2b Fix xenmaker crashing when many of them are activated simultaneously. 2023-10-06 19:44:17 -03:00
Giegue
c1660a0e48 Add env_xenmaker entity. 2023-10-06 01:43:56 -03:00
Giegue
efb7a1117b Merge pull request #18 from JulianR0/tier4
Tier4
2023-09-12 17:08:06 -03:00
Giegue
91f34169b5 Update some texts. 2023-09-12 16:43:12 -03:00
Giegue
272482c5e7 A long overdue update...
- Fixed Alien Grunt's hornets being silent.
- Fixed many, many, many, many ... many GSR crashes.
- Fixed voltigore's beams not being cleared upon gibbing/removal.
- Prepare for T4 release.
2023-09-12 13:51:25 -03:00
Giegue
12f8eea011 Yet another GMR/GSR fix.
Monster maximum viewable distance is now customizable.
2023-07-01 18:23:59 -03:00
Giegue
1d2a284197 Fixed mistyped monster_bullchicken classname.
Fixed ambient_music not stopping sounds during mapchange.
Fixed monster_gargantua crashing the server upon death.
Fixed GMR/GSR being prone to crashing.
Fixed monster_human_grunt melee attack not damaging non-mm entities.
Fixed monster_male_assassin doing sentence speeches.
Fixed monster_shockroach using headcrab sounds for attack.
Removed CGraph::HandleLinkEnt capabilities as they crash the server.
Increased monster_alien_voltigore lightning attack range.
2023-07-01 16:27:32 -03:00
Giegue
fbe70a5691 Fix sound replacements crashing the server. 2023-06-01 19:46:02 -03:00
Giegue
b87538ff59 Fix monstermaker attempting to spawn alien grunt when monster type is undefined or invalid. 2023-06-01 10:32:28 -03:00
Giegue
fa39abd61c Fix BSP reader crashing the server, again. 2023-05-31 16:16:37 -03:00
Giegue
95461427b2 Add sentences support. 2023-05-02 23:40:00 -03:00
Giegue
c782c2aaf5 Fixed a heap corruption. 2023-04-30 11:32:12 -03:00
Giegue
efd801bdea Add "soundlist" keyvalue for individual sound replacements. 2023-04-29 02:04:40 -03:00
Giegue
92d14a6fd3 Update extra AMXX plugins. 2023-04-29 01:58:47 -03:00
Giegue
ba9414ea6e Add missing keyvalue in monstermaker.
Fix duplicate entity spawn in Half-Life.
2023-04-27 13:02:23 -03:00
Giegue
f751720e59 Recompile AMXX plugins (Did I forget to update them?). 2023-04-27 12:59:29 -03:00
Giegue
0ac8fc00d5 Merge branch 'tier4' of https://github.com/JulianR0/monstermod-redo into tier4 2023-04-26 01:45:28 -03:00
Giegue
5da691b5fe Fix apache/turrets not triggering their targets on death.
Fix apache not giving score upon kill.
Fix monster trigger target crashing the server.
Add "squadmaker" alias entity.
Added plenty of keyvalues to monstermaker, similar to SC's squadmaker.
2023-04-26 01:44:36 -03:00
Giegue
ec45c6f23b Merge branch 'tier4' of https://github.com/JulianR0/monstermod-redo into tier4 2023-04-25 22:33:53 -03:00
Giegue
d00fec91b8 Update extra AMXX plugins. 2023-04-25 22:32:36 -03:00
Giegue
e1e2a48f89 Fix Alien Grunt's TraceAttack method.
Fix extra cfg file crashing the server.
Added custom blood color for monsters.
2023-04-24 13:17:49 -03:00
Giegue
1d8a6768aa Fix monster blood not working.
Fix monster hitboxes not working.
2023-04-24 01:30:52 -03:00
Giegue
2cf22ab66b Fix Makefiles. 2023-04-23 13:43:10 -03:00
Giegue
bfa59a2419 Fix Male Assassin unable to use the Sniper Rifle.
Partially fixed the Stukabat being unable to move when target is unreachable.
Removed zombie/gonome bullet resistance.
Add Global Model Replacement and Global Sound Replacement.
Update Tier milestones.
2023-04-21 20:55:47 -03:00
Giegue
66be4861a3 Fix male assassin unable to use weapons properly.
Remove zombie/gonome bullet resistance.
Make it slighly harder to gib monsters.
Small navigation fix.
Fix compilation on Visual Studio 2015 and 2017.
Fix "use_monstermod" keyvalue not working.
2023-04-15 19:23:20 -03:00
Giegue
fb92c2369f Remove unsupported door info in AI navigation.
Fix keyvalue length being too small.
2023-04-03 12:51:01 -03:00
Giegue
62c17b14e4 Even more BSP reader fixes.
Also fix project file not including all files.
2023-04-01 23:57:11 -03:00
Giegue
28c18952f8 Fix BSP reader breaking when there are too many entities. 2023-04-01 03:03:17 -03:00
Giegue
18268776ae This objetive is complete. 2023-03-29 12:57:37 -03:00
Giegue
acc22bc9ef Fix BSP reader crashing the server. 2023-03-29 12:54:54 -03:00
Giegue
79d4b3b21d Read entities within the BSP itself.
NOT YET COMPLETE, HIGHLY UNSTABLE!

Disabled by default, prone to crashing under Windows.
Set CVar "monster_entity_config" to 0 (or 2) to enable reading from BSP.
2023-03-29 02:48:18 -03:00
Giegue
074635bf8d Derp. Fixed an inverted check. 2023-03-25 21:52:57 -03:00
Giegue
a3086aaaa4 Print number of entities found in BSP file.
Add 'ambient_music' entity.
2023-03-25 21:48:27 -03:00
Giegue
c813f6e76a Fix entvars keyvalues not working.
Fix monstermaker classname.
2023-03-25 21:46:22 -03:00
Giegue
b757c65345 Forgotten header update for windows compilation. 2023-03-16 16:06:45 -03:00
Giegue
ecf3bd9a3d Fixed tons of monsters not working/crashing when attacking HL monsters. 2023-03-16 15:58:09 -03:00
Giegue
bc7633bf9c Update readme. 2023-03-15 14:23:44 -03:00
Giegue
3b1c99d2cc [#11] Add basic death message on PvP kills. 2023-03-15 14:09:06 -03:00
Giegue
5478860f27 Merge branch 'tier4' of https://github.com/JulianR0/monstermod-redo into tier4 2023-03-15 14:07:20 -03:00
Giegue
76d4c3b4bd Compile under modern Visual Studio versions. 2023-03-15 14:06:02 -03:00
Giegue
9849c5296b Add link to wiki. 2023-03-08 19:17:38 -03:00
Giegue
b364915799 [#10] Fix linux compilation. 2023-03-07 13:47:03 -03:00
Giegue
bd9fe1f487 Handle entvar keyvalues. 2023-03-06 20:02:04 -03:00
Giegue
73f240ddb1 Fixed monster turn rate being too slow.
Fixed heavy weapons grunt AI being complete nonsense.
Small improvements to stukabat.
2023-03-06 02:08:37 -03:00
Giegue
750b916666 *screams in AI* 2023-03-04 17:24:23 -03:00
Giegue
bd02a95260 Fix broken shock roach death.
Fix hwgrunt not spinning down the minigun.
Other misc. fixes.
2023-03-04 17:24:01 -03:00
Giegue
62063e34da Scrap scaling idea, not possible. 2023-03-03 01:33:37 -03:00
Giegue
55dfee7d74 Fixed human grunts refusing to attack and refusing to reload.
This also fixes male assassins and shock troopers behaving erraticaly.
Probably the heavy weapons grunt becomes better, too.
2023-03-03 01:18:38 -03:00
Giegue
2140e3413d [#4] Fix compiler warnings. 2023-03-02 14:09:49 -03:00
Giegue
e1bd51b220 [#4] Fix wrong angles on shocktroopers beams and roaches. 2023-03-02 14:09:15 -03:00
Giegue
4b087efde8 I keep forgetting to update this... 2023-02-28 13:46:44 -03:00
Giegue
08846e8dee Merge pull request #6 from JulianR0/tier4
Fix 'git clone' not working on Lubuntu 22.10
2023-02-28 13:19:28 -03:00
Giegue
7075efe7d9 Fixed git clone not working because some distros REALLY dislike the "aux" name! 2023-02-28 13:14:04 -03:00
Giegue
b265a65fe1 Fixed damageBits not being catched for death messages.
Removed DeathMsg manipulation, it never worked correctly.
2023-02-27 10:27:21 -03:00
Giegue
4c7579c3e2 Merge pull request #5 from JulianR0/tier3
Tier3
2023-02-24 16:07:32 -03:00
Giegue
035e70e776 Update config files. 2023-02-24 15:29:07 -03:00
Giegue
d4ecb16bf7 Add custom model support. 2023-02-24 14:49:55 -03:00
Giegue
513cde6231 Add compatibility with Half-Life. 2023-02-23 03:29:53 -03:00
Giegue
e33eaf4d1e Full awareness of normal game entities. 2023-02-22 22:29:19 -03:00
Giegue
e29e79052d Use the game's generated graph if possible. 2023-02-21 20:16:11 -03:00
Giegue
8d28e23e16 Fixed wrong classname for Voltigore and Baby Voltigore.
Fixed unknown classnames showing as '}'.
Remove monster respawn.
Add 'monstermaker' entity.
2023-02-20 14:08:35 -03:00
Giegue
0622ccc638 Stop allied monsters from attacking the player.
Part B of making MonsterMod aware of normal HL entities.
2023-02-19 15:57:07 -03:00
Giegue
6e1081d793 Start making monstermod aware of normal HL monsters.
This is still heavily experimental and its use is not yet recommended.
2023-02-15 21:19:57 -03:00
Giegue
5830ac7908 Tweaked hwgrunt to be less crappy. 2023-02-15 21:14:13 -03:00
Giegue
2f80da1e15 Fix linux compilation.
Fix windows compilation, again.
2023-02-14 20:44:13 -03:00
Giegue
c32827b4cb Update milestones, again. 2023-02-07 18:32:55 -03:00
Giegue
5f7abc2df0 Add monster_stukabat. 2023-02-07 18:19:52 -03:00
Giegue
875d6610ae Add monster_robogrunt. 2023-02-05 17:13:39 -03:00
Giegue
94fc64226c Update README and milestones. 2023-02-03 03:04:08 -03:00
Giegue
19b7c69b14 Add monster_hwgrunt. 2023-02-03 02:37:30 -03:00
Giegue
0fd2d27b6f Fix windows compilation. 2023-02-01 01:07:35 -03:00
Julian
87210e5f6c Update readme to add information about precache. 2020-07-30 00:04:08 -03:00
Julian
9df28b9d3f Added monster_babygarg. 2020-07-29 22:35:01 -03:00
Julian
9602f862c9 Added monster_voltigore and monster_baby_voltigore. 2020-07-19 12:31:52 -03:00
Julian
5b0ced8e7d Add monster_shocktrooper. 2020-06-30 23:17:53 -03:00
Julian
63779c0471 Randomize Male Assassin weapons. 2020-06-12 04:26:25 -03:00
Julian
433bb24dcd Add monster_pitdrone. 2020-06-11 01:30:29 -03:00
Julian
ba25f7710c Add monster_otis. 2020-06-10 01:12:58 -03:00
Julian
bf607621b3 Add monster_male_assassin. 2020-06-09 18:21:51 -03:00
Julian
769ec8852f Update monster IRelationship to match Sven Co-op 5.x table. 2020-06-08 03:52:27 -03:00
Julian
7fcf39b6d3 Add monster_gonome. 2020-06-07 18:52:55 -03:00
Julian
2762dbc0b2 Update README. 2020-06-04 15:06:47 -03:00
180 changed files with 66287 additions and 52923 deletions

View File

@@ -21,27 +21,59 @@ A small light is seen at the distance...
## What is this? ## What is this?
MonsterMod is a MetaMod plugin. It's purpose was to allow support for monsters to spawn in multiplayer games where they are not. The project updates became incredibly obscure, getting up-to-date versions and the new additions was very difficult. And the only one who had even futher progress kept the plugin private. MonsterMod is a MetaMod plugin. Its purpose was to allow multiplayer games to add monsters, where it wasn't possible to do so by normal means. The updates of the project became incredibly obscure: Getting the "up-to-date" versions containing the new additions (opposing force monsters, for example) were very difficult. And the only one who managed to bring the plugin even futher kept the progress of the plugin private.
Nearly 18 years after botman's original plugin was released, the future of the project became nothing but a forgotten, ancient relic of the past. After 21 years since botman's original plugin was released, the future of the project became nothing but a forgotten, ancient relic of the past.
Not anymore... Not anymore...
This project aims towards the recreation of the new features of the "obscured and updated" Monster Mod plugin. Taking botman's original 2002 plugin and working up from the ground, and to rebuild it with the new features and monsters that only few were able to see. The first goal of this project aims towards the recreation of the new features of the "obscured and updated" Monster Mod plugin. Taking botman's original 2002 plugin and working from the ground up, the mission is to rebuild it with the new features and monsters that only few were able to see.
The source code is completely free to use for everyone: In the event that the development of this new project falls and becomes stagnant again, the plugin will live on, as the project's second goal is it's preservation. The original botman's page where you can download the 2002 plugin will not stay up forever. The source code is completely free for everyone to use: In the event that the development of this project falls and becomes stagnant again, the plugin will live on, as the project's second goal is its preservation. ~~The original botman's page where you can download the 2002 plugin will not stay up forever.~~ **April 2023 update**: The page is gone, the original 2002 plugin can no longer be found.
Under no circumstances we shall allow this project to fade away and become lost amidst the gears of time. Under no circumstances shall we allow this project to fade away and become lost amidst the gears of time.
## Installation
The plugin -should- be able to be used out-of-the-box by simply downloading the binary and adding the appropiate entry in metamod's plugin list.
**Windows:**
`win32 addons\monstermod\monster_mm.dll`
**Linux:**
`linux addons/monstermod/monster_mm_i386.so`
To start adding monsters onto your maps, additional configuration files are included in the release files, each explaining its usage and installation instructions. Nevertheless, if you are felling lost, the [wiki](https://github.com/JulianR0/monstermod-redo/wiki) contains usage instructions, and how to configure MonsterMod to your liking.
Extra MonsterMod features can be unlocked with additional AMX Mod X plugins which are located in the `extra` folder. All these plugins are optional, and only required based on your use-case.
## Build Instructions
The [Building](https://github.com/JulianR0/monstermod-redo/wiki) section of the wiki contains instructions on how to compile MonsterMod by yourself.
## MonsterMod and ReHLDS
Usage of ReHLDS is highly recommended, as you can use the command `rescount` which will reveal the current number of precached models and sounds. You can also use `reslist model` and `reslist sound` to see the entire list of precached content.
Keeping track of the number of precached content will allow you to maximize the number of monsters you can use without risking going over the limits.
## Known Bugs and Issues
I'm aware that the plugin is far from perfect, and there are a few things that need polishing *-especially the AI-*. I'll try to fix/will be fixing as the project evolves:
- Rarely, Stukabats will become unable to fly towards their target, standing in air doing seemingly nothing.
- Monsters are very prone to gibbing.
- Houndeyes and Hornets (Alien Grunts) do not get along. The server will crash if a houndeye damages a hornet.
There are probably more issues that aren't listed here, I'll attempt to fix them as I find them. Of course, any bug report is welcome. If reporting a bug, try to explain step by step how the bug ocurred. The easier it is to replicate a bug, the easier it is to locate it and fix it.
## Milestones ## Milestones
Attempting to recreate everything in one go is a daunting task. Attempting to recreate everything in one go is a daunting task.
Let it be known that the original 2002 source code will NOT compile on today's compilers, and does NOT contain all the necessary files for compilation. The preliminary was to rewrite and provide as many files or lines of code to ensure it can compile again, and be usable on an actual HLDS installation. Let it be known that the original 2002 source code will NOT compile on today's compilers, and does NOT contain all the necessary files for compilation. The preliminary was to rewrite and provide as many files or lines of code to ensure it can compile again, and be usable on an actual HLDS installation.
Currently, I aim working this for linux only. While the original 2002 Visual C++ DSP file exists in the repository, it has not been updated to newer formats. Who knows if it can even open on newer Visual Studio versions, let alone, to compile?
Even so, in linux, I had to resort to compile under GCC 4.8 for the plugin to work. While I could use a newer compiler (GCC 9 at the time of this writing), whenever or not the plugin will run is dependant on the HLDS installation and the system libraries is it hosted with. If you compile with newer GCC compilers, be warned that it may refuse to load, as it will complain about libstdc++ not having CXXABI_1.X.X or similar.
Current milestones are separated by "Tiers", which are as follows: Current milestones are separated by "Tiers", which are as follows:
### Tier 0 ### Tier 0
@@ -63,19 +95,31 @@ Current milestones are separated by "Tiers", which are as follows:
### Tier 3 ### Tier 3
- Implement *-almost-* all Opposing Force monsters. - Update source code so it can compile AND run **ON WINDOWS**. **[DONE]**
- Implement *-almost-* all default Sven Co-op monsters. - Implement *-almost-* all Opposing Force monsters. **[DONE]**
- Add configurations to change AI behaviour. - Implement *-almost-* all default Sven Co-op monsters. **[DONE]**
- Make MonsterMod aware of normal game entities. *-For those wanting to use this in vanilla HL.-* **[DONE]**
- Custom model support. **[DONE]**
### Tier 4 ### Tier 4
- Custom model support, along with scaling. - Implement reading entities within the BSP itself. **[DONE]**
- Custom sound support. - Add build instructions. **[DONE]**
- Implement extra entities to enhance map gameplay. - Global Model Replacement. **[DONE]**
- Global Sound Replacement. **[DONE]**
- Miscellaneous customization options, such as blood color. **[DONE]**
- Individual sound replacement: "soundlist" keyvalue for monsters. **[DONE]**
- Sentences support for speakable monsters. **[DONE]**
- Attempt to fix bugs as they appear. **[DONE]**
### Tier 5 ### Tier 5
- Update source code so it can compile AND run **ON WINDOWS**. - Enhance the AI.
- Add configurations to change AI behaviour.
- Create "tool" entities for easier map customization.
- Optimize and clean the code.
- Add a wiki with full documentation.
- Fix **ALL** bugs, specially those not covered in Tier 4.
What will the future hold after all Tiers has been completed? What will the future hold after all Tiers has been completed?

View File

@@ -2,33 +2,13 @@
// Make a copy of this file and rename it to "<mapname>_monster.cfg". // Make a copy of this file and rename it to "<mapname>_monster.cfg".
// Send this new file to your maps folder. // Send this new file to your maps folder.
// //
// To add entries to this file, just pretend it's ripent. // Adding entities to this file is done in the same way as ripenting a map.
// //
// "delay" means monster respawndelay. // For more detailed instructions, check the wiki at
// // https://github.com/JulianR0/monstermod-redo/wiki
// You may also be interesed in these other 2 keyvalues:
//
// "displayname" to change the monster's name, shown in HUD when you point at it.
// "classify" to change the monster's default classification, use one of these values:
//
// CLASS_NONE 0
// CLASS_MACHINE 1
// CLASS_PLAYER 2
// CLASS_HUMAN_PASSIVE 3
// CLASS_HUMAN_MILITARY 4
// CLASS_ALIEN_MILITARY 5
// CLASS_ALIEN_PASSIVE 6
// CLASS_ALIEN_MONSTER 7
// CLASS_ALIEN_PREY 8
// CLASS_ALIEN_PREDATOR 9
// CLASS_INSECT 10
// CLASS_PLAYER_ALLY 11
// CLASS_PLAYER_BIOWEAPON 12
// CLASS_ALIEN_BIOWEAPON 13
{ {
"origin" "90 -180 150" "origin" "90 -180 150"
"delay" "30"
"displayname" "Example Custom Name" "displayname" "Example Custom Name"
"orientation" "1" "orientation" "1"
"spawnflags" "32" "spawnflags" "32"
@@ -36,7 +16,6 @@
} }
{ {
"origin" "123 456 789" "origin" "123 456 789"
"delay" "5"
"classify" "7" "classify" "7"
"angles" "0 45 0" "angles" "0 45 0"
"classname" "monster_houndeye" "classname" "monster_houndeye"

View File

@@ -1,16 +1,19 @@
// This file constains the monsters that you always want to precache for dynamic spawning.
// //
// MONSTERS - monsters that you always want to precache (for dynamic spawning) // Dynamic spawning means - Monsters that you want to invoke at any time, on any map.
// //
// Install this file to your mod's base directory. // Install this file to your mod's base directory.
// Then, remove the comment characters at the beginning of the line for the
// monsters that you always want to precache.
// //
// (just remove the comment characters at the beginning of the line for the // Be wary if you precache too many monsters, it may easily crash your
// monsters that you always want to precache.) // server due to the age-old 512 limit.
//monster_alien_grunt //monster_alien_grunt
//monster_apache //monster_apache
//monster_barney //monster_barney
//monster_bigmomma //monster_bigmomma
//monster_bullsquid //monster_bullchicken
//monster_gargantua //monster_gargantua
//monster_human_assassin //monster_human_assassin
//monster_headcrab //monster_headcrab
@@ -24,3 +27,14 @@
//monster_turret //monster_turret
//monster_miniturret //monster_miniturret
//monster_sentry //monster_sentry
//monster_gonome
//monster_male_assassin
//monster_otis
//monster_pitdrone
//monster_shocktrooper
//monster_alien_voltigore
//monster_alien_babyvoltigore
//monster_babygarg
//monster_hwgrunt
//monster_robogrunt
//monster_stukabat

View File

@@ -2,6 +2,9 @@
// //
// Install this file to your mod's base directory. // Install this file to your mod's base directory.
// ORIGINAL HALF-LIFE MONSTERS
// Alien Grunt // Alien Grunt
sk_agrunt_health 90 sk_agrunt_health 90
sk_agrunt_dmg_punch 20 sk_agrunt_dmg_punch 20
@@ -13,7 +16,7 @@ sk_apache_health 250
// Barney // Barney
sk_barney_health 35 sk_barney_health 35
// Big Momma // Big Momma (HP = 150 * health_factor)
sk_bigmomma_health_factor 1.5 sk_bigmomma_health_factor 1.5
sk_bigmomma_dmg_slash 60 sk_bigmomma_dmg_slash 60
sk_bigmomma_dmg_blast 120 sk_bigmomma_dmg_blast 120
@@ -55,10 +58,6 @@ sk_islave_dmg_claw 10
sk_islave_dmg_clawrake 25 sk_islave_dmg_clawrake 25
sk_islave_dmg_zap 10 sk_islave_dmg_zap 10
// Icthyosaur
sk_ichthyosaur_health 200
sk_ichthyosaur_shake 35
// Controller // Controller
sk_controller_health 60 sk_controller_health 60
sk_controller_dmgzap 25 sk_controller_dmgzap 25
@@ -88,8 +87,75 @@ sk_miniturret_health 40
// Sentry Turret // Sentry Turret
sk_sentry_health 40 sk_sentry_health 40
// OPPOSING FORCE MONSTERS
// Gonome
sk_gonome_health 85
sk_gonome_dmg_one_slash 20
sk_gonome_dmg_guts 10
sk_gonome_dmg_one_bite 14
// Male Assassin
sk_massassin_health 50
sk_massassin_kick 25
// Otis
sk_otis_health 35
// Pit Drone
sk_pitdrone_health 40
sk_pitdrone_dmg_bite 25
sk_pitdrone_dmg_whip 35
sk_pitdrone_dmg_spit 10
// Shock Roach
sk_shockroach_health 10
sk_shockroach_lifespan 10
// ShockTrooper
sk_shocktrooper_health 50
sk_shocktrooper_kick 10
sk_shocktrooper_maxcharge 8
sk_shocktrooper_rchgspeed 1
sk_shock_dmg 15
sk_spore_dmg 50
// Voltigore
sk_voltigore_health 320
sk_voltigore_dmg_beam 50
sk_voltigore_dmg_punch 40
// Baby Voltigore
sk_babyvoltigore_health 60
sk_babyvoltigore_dmg_punch 15
// SVEN CO-OP MONSTERS
// Baby Gargantua
sk_babygarg_health 640
sk_babygarg_dmg_slash 24
sk_babygarg_dmg_fire 4
sk_babygarg_dmg_stomp 80
// Heavy Weapons Grunt
sk_hwgrunt_health 100
// Robo Grunt
sk_rgrunt_health 50
sk_rgrunt_armor 0.75
// Stukabat
sk_stukabat_health 80
sk_stukabat_dmg_bite 11
sk_stukabat_speed 400
// MONSTER WEAPON DAMAGE // MONSTER WEAPON DAMAGE
sk_9mm_bullet 5 sk_9mm_bullet 5
sk_9mmAR_bullet 4 sk_9mmAR_bullet 4
sk_9mmAR_grenade 100 sk_9mmAR_grenade 100
sk_12mm_bullet 10 sk_12mm_bullet 10
sk_762_bullet 100
sk_357_bullet 40

9
extra/README.md Normal file
View File

@@ -0,0 +1,9 @@
## Auxiliary Tools
This folder contains auxiliary tools used to enhance the compatibility and/or interaction of MonsterMod with other mods.
As these are auxiliary, they aren't needed to enjoy MonsterMod. If you want an extra boost, feel free to install these.
Plugins from the `base` folder should come first, then the ones from the appropiate mod folder.
Once all milestones are completed, the possibility of removing the need for external plugins will be considered. Until then, this has to stay.

29
extra/base/README.md Normal file
View File

@@ -0,0 +1,29 @@
## Base Plugins (All Mods)
Auxiliary Tools to use MonsterMod in any GoldSrc game.
These are base plugins that should be installed first before adding any mod-specific plugin.
### AMX Mod X Plugins
#### -A note about AMXX plugins-
All plugins in this section require AMXX 1.9.0 or greater, they will not work on 1.8.2 or older.
Compiled plugins are provided in the `bin` folder for your convenience. However, if you prefer to build the plugins yourself, the source code of all AMXX plugins are located in the `src` folder for compilation.
#### Use Dispatcher
Because MonsterMod entities are, -quite literally-, just a func_wall with its own logic, trying to trigger any MonsterMod entity from the outside will fail, as it will attempt to use the logic of game's "func_wall" instead of our own.
In normal circunstances, you do not need this plugin. But let's say you have a turret monster, disabled by default, and you gave it a targetname. Even with a name, triggering this turret regardless of the method used will not activate it.
The same problem occurs from the other side, a MonsterMod entity trying to trigger something will expect said entity to be part of MonsterMod as well.
This plugin redirects the game's func_wall Use() function to MonsterMod, as well as bridging Use() calls from MonsterMod back to the game, connecting the missing pieces and allowing you to trigger MonsterMod entities from the game, and game entities from MonsterMod.
#### External TakeDamage
When a MonsterMod entity tries to inflict damage to something, it expects said entity to be either a player or a MonsterMod monster. If something else is to be found, it will deal no damage to it, as it doesn't know how to manage it.
This plugin allows MonsterMod entities to inflict damage to normal game entities, such as breakables.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,57 @@
#pragma semicolon 1
#include <amxmodx>
#include <engine>
#include <hamsandwich>
public plugin_init()
{
register_plugin( "GAME-MONSTER: Use Dispatcher", "1.1", "Giegue" );
register_cvar( "_glb_use", "1" );
// Game --> MonsterMod
RegisterHam( Ham_Use, "func_wall", "DispatchUse" );
// MonsterMod --> Game
register_srvcmd( "_trigger", "FireTargets" );
}
public DispatchUse( entity, caller, activator, useType, Float:value )
{
// all monstermod entities have this set
if ( entity_get_edict( entity, EV_ENT_euser4 ) )
{
server_cmd( "_use %i %i %i %i %f", entity, caller, activator, useType, value );
return HAM_SUPERCEDE;
}
return HAM_IGNORED;
}
public FireTargets()
{
if ( read_argc() == 6 )
{
new entity, caller, activator;
new Float:value;
new useType;
entity = read_argv_int( 1 );
caller = read_argv_int( 2 );
activator = read_argv_int( 3 );
value = read_argv_float( 4 );
useType = read_argv_int( 5 );
// caller and activator can be null, but never allow entity to be null
if ( !is_valid_ent( entity ) )
return;
if ( !is_valid_ent( caller ) )
caller = 0;
if ( !is_valid_ent( activator ) )
activator = 0;
ExecuteHamB( Ham_Use, entity, caller, activator, useType, value );
}
}

View File

@@ -0,0 +1,42 @@
#pragma semicolon 1
#include <amxmodx>
#include <engine>
#include <hamsandwich>
public plugin_init()
{
register_plugin( "GAME-MONSTER: External TakeDamage", "1.0", "Giegue" );
register_cvar( "_glb_takedamage", "1" );
// MonsterMod --> Game
register_srvcmd( "_takedamage", "TakeDamage" );
}
public TakeDamage()
{
if ( read_argc() == 6 )
{
new victim, inflictor, attacker;
new Float:damage;
new damageBits;
victim = read_argv_int( 1 );
inflictor = read_argv_int( 2 );
attacker = read_argv_int( 3 );
damage = read_argv_float( 4 );
damageBits = read_argv_int( 5 );
// attacker and inflictor can be null, but never allow victim to be null
if ( !is_valid_ent( victim ) )
return;
if ( !is_valid_ent( inflictor ) )
inflictor = 0;
if ( !is_valid_ent( attacker ) )
attacker = 0;
ExecuteHamB( Ham_TakeDamage, victim, inflictor, attacker, damage, damageBits );
}
}

17
extra/cstrike/README.md Normal file
View File

@@ -0,0 +1,17 @@
## Counter-Strike (cstrike)
Auxiliary Tools to use MonsterMod in Counter-Strike.
### AMX Mod X Plugins
#### -A note about AMXX plugins-
All plugins in this section require AMXX 1.9.0 or greater, they will not work on 1.8.2 or older.
Compiled plugins are provided in the `bin` folder for your convenience. However, if you prefer to build the plugins yourself, the source code of all AMXX plugins are located in the `src` folder for compilation.
#### Unprecacher
Counter-Strike precaches the sounds of all weapons. This means that sounds such as "clip-ins", "clip-outs" are added to the list, taking quite a bit of space in the precache count. Let it be a reminder that our good old GoldSrc can only store a maximum of 512 precached resources. Most of these sounds are handled client-side by the models themselves, so there is no need for them to be kept precached on the server. Only the weapons fire sounds are needed.
This plugin removes 85 sounds from the precache list, adding extra space for additional monsters to fit in the map.

Binary file not shown.

View File

@@ -0,0 +1,126 @@
#pragma semicolon 1
#include <amxmodx>
#include <fakemeta>
// List of sounds that must NOT be precached
new g_SoundList[][64] =
{
"weapons/ak47_boltpull.wav",
"weapons/ak47_clipin.wav",
"weapons/ak47_clipout.wav",
"weapons/aug_boltpull.wav",
"weapons/aug_boltslap.wav",
"weapons/aug_clipin.wav",
"weapons/aug_clipout.wav",
"weapons/aug_forearm.wav",
"weapons/awp_clipin.wav",
"weapons/awp_clipout.wav",
"weapons/awp_deploy.wav",
"weapons/boltdown.wav",
"weapons/boltpull1.wav",
"weapons/boltup.wav",
"weapons/clipin1.wav",
"weapons/clipout1.wav",
"weapons/de_clipin.wav",
"weapons/de_clipout.wav",
"weapons/de_deploy.wav",
"weapons/elite_clipout.wav",
"weapons/elite_deploy.wav",
"weapons/elite_leftclipin.wav",
"weapons/elite_reloadstart.wav",
"weapons/elite_rightclipin.wav",
"weapons/elite_sliderelease.wav",
"weapons/elite_twirl.wav",
"weapons/famas_boltpull.wav",
"weapons/famas_boltslap.wav",
"weapons/famas_clipin.wav",
"weapons/famas_clipout.wav",
"weapons/famas_forearm.wav",
"weapons/fiveseven_clipin.wav",
"weapons/fiveseven_clipout.wav",
"weapons/fiveseven_slidepull.wav",
"weapons/fiveseven_sliderelease.wav",
"weapons/g3sg1_clipin.wav",
"weapons/g3sg1_clipout.wav",
"weapons/g3sg1_slide.wav",
"weapons/galil_boltpull.wav",
"weapons/galil_clipin.wav",
"weapons/galil_clipout.wav",
"weapons/m4a1_boltpull.wav",
"weapons/m4a1_clipin.wav",
"weapons/m4a1_clipout.wav",
"weapons/m4a1_deploy.wav",
"weapons/m4a1_silencer_off.wav",
"weapons/m4a1_silencer_on.wav",
"weapons/m249_boxin.wav",
"weapons/m249_boxout.wav",
"weapons/m249_chain.wav",
"weapons/m249_coverdown.wav",
"weapons/m249_coverup.wav",
"weapons/mac10_boltpull.wav",
"weapons/mac10_clipin.wav",
"weapons/mac10_clipout.wav",
"weapons/mp5_clipin.wav",
"weapons/mp5_clipout.wav",
"weapons/mp5_slideback.wav",
"weapons/p90_boltpull.wav",
"weapons/p90_clipin.wav",
"weapons/p90_clipout.wav",
"weapons/p90_cliprelease.wav",
"weapons/p228_clipin.wav",
"weapons/p228_clipout.wav",
"weapons/p228_slidepull.wav",
"weapons/p228_sliderelease.wav",
"weapons/scout_bolt.wav",
"weapons/scout_clipin.wav",
"weapons/scout_clipout.wav",
"weapons/sg550_boltpull.wav",
"weapons/sg550_clipin.wav",
"weapons/sg550_clipout.wav",
"weapons/sg552_boltpull.wav",
"weapons/sg552_clipin.wav",
"weapons/sg552_clipout.wav",
"weapons/slideback1.wav",
"weapons/sliderelease1.wav",
"weapons/ump45_boltslap.wav",
"weapons/ump45_clipin.wav",
"weapons/ump45_clipout.wav",
"weapons/usp_clipin.wav",
"weapons/usp_clipout.wav",
"weapons/usp_silencer_off.wav",
"weapons/usp_silencer_on.wav",
"weapons/usp_slideback.wav",
"weapons/usp_sliderelease.wav"
};
public plugin_init()
{
register_plugin( "CS-MONSTER: Unprecacher", "1.0", "Giegue" );
}
public plugin_precache()
{
register_forward( FM_PrecacheSound, "fw_PrecacheSound" );
}
public fw_PrecacheSound( const sound[] )
{
static bool:bBlock, i;
bBlock = false;
i = 0;
for ( i = 0; i < sizeof( g_SoundList ); i++ )
{
if (contain( sound, g_SoundList[ i ] ) != -1 )
{
bBlock = true;
break;
}
}
if ( bBlock )
return FMRES_SUPERCEDE;
return FMRES_IGNORED;
}

40
extra/valve/README.md Normal file
View File

@@ -0,0 +1,40 @@
## Half-Life (valve)
Auxiliary Tools to use MonsterMod in the original Half-Life.
### AMX Mod X Plugins
#### -A note about AMXX plugins-
All plugins in this section require AMXX 1.9.0 or greater, they will not work on 1.8.2 or older.
Compiled plugins are provided in the `bin` folder for your convenience. However, if you prefer to build the plugins yourself, the source code of all AMXX plugins are located in the `src` folder for compilation.
#### Bridge Plugin
MonsterMod monsters are hacked "func_wall"'s with simulated AI. Because of this, MonsterMod cannot interact with the Half-Life monsters. This issue also happens on the other side: The Half-Life monsters cannot interact with the MonsterMod monsters.
In simple terms, this plugin acts as a "bridge" to help Half-Life and MonsterMod communicate with each other. With this plugin, HL and MM monsters can "see" and interact with each other, and will react accordingly.
Without this plugin, HL and MM monsters will be "invisible" to each other.
#### Soundlist
This plugin allows you to use the "soundlist" keyvalue in HL monsters to individually replace monster sounds. Path starts from `sound/MAPNAME`. Use `../` to go to the previous directory if needed.
The plugin can work standalone, meaning it can be used without MonsterMod.
#### Extra Keyvalues
**"Bridge Plugin" is REQUIRED for this add-on to work**
This plugin allows you use the following keyvalues on HL monsters:
- classify
- is_player_ally *(non-monstermaker entities)*
- bloodcolor
- respawn_as_playerally *(monstermaker entity)*
The plugin also adds a 5th keyvalue, **"use_monstermod"**. When reading entities from the BSP file, if MonsterMod finds an entity that already exists in the game, it will stick to the game entity and ignore it. By setting this keyvalue to "1", it will explicity use MonsterMod for this entity.
This is useful when, for example, you are trying to spawn a Pit Drone from a monstermaker. HL does not recognize monster_pitdrone, but MonsterMod does. By redirecting the entity to MonsterMod, Pit Drones will spawn from this monstermaker.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,232 @@
#pragma semicolon 1
#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <hamsandwich>
const bits_MEMORY_SPAWN = ( 1 << 1 );
const BLOOD_COLOR_BLUE = 211;
const BLOOD_COLOR_PINK = 147;
const BLOOD_COLOR_WHITE = 11;
const BLOOD_COLOR_ORANGE = 231;
const BLOOD_COLOR_BLACK = 49; // not 100% black but close enough
const BLOOD_COLOR_DARKGREEN = 181; // GREEN is aliased to YELLOW, use custom name
public plugin_init()
{
register_plugin( "HL-MONSTER Extra Keyvalues", "1.0", "Giegue" );
/* CLASSIFY */
// HACK: since Ham_Spawn won't work, this should do as an alternative
RegisterHam( Ham_SetObjectCollisionBox, "monster_headcrab", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_babycrab", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_bullchicken", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_barnacle", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_bigmomma", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_houndeye", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_slave", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_controller", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_grunt", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_zombie", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_ichthyosaur", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_human_grunt", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_human_assassin", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_barney", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_gman", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_scientist", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_sentry", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_snark", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_miniturret", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_turret", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_apache", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_osprey", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_gargantua", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_nihilanth", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_tentacle", "MonsterSpawn_Post", 1 );
/* BLOODCOLOR */
RegisterHam( Ham_BloodColor, "monster_headcrab", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_babycrab", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_bullchicken", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_barnacle", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_bigmomma", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_houndeye", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_alien_slave", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_alien_controller", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_alien_grunt", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_zombie", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_ichthyosaur", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_human_grunt", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_human_assassin", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_barney", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_gman", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_scientist", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_sentry", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_snark", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_miniturret", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_turret", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_apache", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_osprey", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_gargantua", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_nihilanth", "MonsterBlood" );
RegisterHam( Ham_BloodColor, "monster_tentacle", "MonsterBlood" );
// "use_monstermod" keyvalue
register_cvar( "_hl_explicit", "1" );
}
public plugin_precache()
{
register_forward( FM_KeyValue, "ScanKeys" );
}
public ScanKeys( entid, kvd_handle )
{
if (is_valid_ent(entid))
{
static classname[ 33 ], keyname[ 33 ], value[ 128 ];
get_kvd( kvd_handle, KV_ClassName, classname, charsmax( classname ) );
// Monsters
if ( equal( classname, "monster_", 8 ) )
{
get_kvd( kvd_handle, KV_KeyName, keyname, charsmax( keyname ) );
get_kvd( kvd_handle, KV_Value, value, charsmax( value ) );
// Classification override
if ( equal( keyname, "classify" ) )
entity_set_int( entid, EV_INT_iuser4, str_to_num( value ) );
// Allied monster
if ( equal( keyname, "is_player_ally" ) )
{
if ( str_to_num( value ) )
entity_set_int( entid, EV_INT_iuser4, 11 ); // CLASS_PLAYER_ALLY
}
// Custom blood color
if ( equal( keyname, "bloodcolor" ) )
{
switch ( str_to_num( value ) )
{
case -1: entity_set_int( entid, EV_INT_iuser3, DONT_BLEED );
// 0 = Monster Default
case 1: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_RED );
case 2: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_YELLOW );
case 3: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_BLUE );
case 4: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_PINK );
case 5: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_WHITE );
case 6: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_ORANGE );
case 7: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_BLACK );
case 8: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_DARKGREEN );
}
}
// Redirect entity to MonsterMod
if ( equal( keyname, "use_monstermod" ) )
{
if ( str_to_num( value ) )
{
// MonsterMod will inherit this entity, remove it from here
remove_entity( entid );
return FMRES_SUPERCEDE;
}
}
return FMRES_IGNORED;
}
// Monster Makers
else if ( equal( classname, "monstermaker" ) )
{
get_kvd( kvd_handle, KV_KeyName, keyname, charsmax( keyname ) );
get_kvd( kvd_handle, KV_Value, value, charsmax( value ) );
// Classification override
if ( equal( keyname, "classify" ) )
entity_set_int( entid, EV_INT_iuser4, str_to_num( value ) );
// Allied monster
if ( equal( keyname, "respawn_as_playerally" ) )
{
if ( str_to_num( value ) )
entity_set_int( entid, EV_INT_iuser4, 11 ); // CLASS_PLAYER_ALLY
}
// Custom blood color
if ( equal( keyname, "bloodcolor" ) )
{
switch ( str_to_num( value ) )
{
case -1: entity_set_int( entid, EV_INT_iuser3, DONT_BLEED );
// 0 = Monster Default
case 1: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_RED );
case 2: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_YELLOW );
case 3: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_BLUE );
case 4: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_PINK );
case 5: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_WHITE );
case 6: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_ORANGE );
case 7: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_BLACK );
case 8: entity_set_int( entid, EV_INT_iuser3, BLOOD_COLOR_DARKGREEN );
}
}
// Redirect entity to MonsterMod
if ( equal( keyname, "use_monstermod" ) )
{
if ( str_to_num( value ) )
{
// MonsterMod will inherit this entity, remove it from here
remove_entity( entid );
return FMRES_IGNORED; // not a typo, must not supercede or it will crash
}
}
return FMRES_IGNORED;
}
}
return FMRES_IGNORED;
}
public MonsterSpawn_Post( entity )
{
// Why is it called 3 times? Restrict this to only once
if ( !( entity_get_int( entity, EV_INT_impulse ) & bits_MEMORY_SPAWN ) )
{
// monstermaker sets owner after monster spawn, wait next frame
set_task( 0.000001, "MakerSpawn_Post", entity );
entity_set_int( entity, EV_INT_impulse, entity_get_int( entity, EV_INT_impulse ) | bits_MEMORY_SPAWN );
}
}
public MakerSpawn_Post( entity )
{
if ( is_valid_ent( entity ) )
{
static owner;
owner = entity_get_edict( entity, EV_ENT_owner );
if ( owner )
{
// pass parent configurations to child entity
entity_set_int( entity, EV_INT_iuser4, entity_get_int( owner, EV_INT_iuser4 ) ); // classify
entity_set_int( entity, EV_INT_iuser3, entity_get_int( owner, EV_INT_iuser3 ) ); // bloodcolor
}
}
}
public MonsterBlood( entity )
{
static newBlood;
newBlood = entity_get_int( entity, EV_INT_iuser3 );
if ( newBlood )
{
SetHamReturnInteger( newBlood );
return HAM_OVERRIDE;
}
return HAM_IGNORED;
}

View File

@@ -0,0 +1,200 @@
#pragma semicolon 1
#include <amxmodx>
#include <engine>
#include <hamsandwich>
// (monster.h from HLSDK) monster to monster relationship types
const R_AL = -2; // (ALLY) pals. Good alternative to R_NO when applicable.
const R_FR = -1; // (FEAR) will run.
const R_NO = 0; // (NO RELATIONSHIP) disregard.
const R_DL = 1; // (DISLIKE) will attack.
const R_HT = 2; // (HATE) will attack this character instead of any visible DISLIKEd characters.
//const R_NM = 3; // (NEMESIS) a monster will ALWAYS attack its nemesis, no matter what.
new Trie:g_HLDefaultNames;
const bits_MEMORY_NAMED = ( 1 << 2 );
public plugin_init()
{
register_plugin( "HL-MONSTER Bridge", "1.2", "Giegue" );
RegisterHam( Ham_IRelationship, "monster_alien_controller", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_alien_grunt", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_alien_slave", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_apache", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_babycrab", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_barnacle", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_barney", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_bigmomma", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_bullchicken", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_gargantua", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_headcrab", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_houndeye", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_human_assassin", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_human_grunt", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_ichthyosaur", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_miniturret", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_scientist", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_sentry", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_snark", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_turret", "mmIRelationship" );
RegisterHam( Ham_IRelationship, "monster_zombie", "mmIRelationship" );
g_HLDefaultNames = TrieCreate();
// Better than a nest of if-else if i guess...
TrieSetString( g_HLDefaultNames, "monster_headcrab", "Head Crab" );
TrieSetString( g_HLDefaultNames, "monster_babycrab", "Baby Head Crab" );
TrieSetString( g_HLDefaultNames, "monster_bullchicken", "Bullsquid" );
TrieSetString( g_HLDefaultNames, "monster_barnacle", "Barnacle" );
TrieSetString( g_HLDefaultNames, "monster_bigmomma", "Big Momma" );
TrieSetString( g_HLDefaultNames, "monster_houndeye", "Houndeye" );
TrieSetString( g_HLDefaultNames, "monster_alien_slave", "Alien Slave" );
TrieSetString( g_HLDefaultNames, "monster_alien_controller", "Alien Controller" );
TrieSetString( g_HLDefaultNames, "monster_alien_grunt", "Alien Grunt" );
TrieSetString( g_HLDefaultNames, "monster_zombie", "Zombie" );
TrieSetString( g_HLDefaultNames, "monster_ichthyosaur", "Ichthyosaur" );
TrieSetString( g_HLDefaultNames, "monster_human_grunt", "Human Grunt" );
TrieSetString( g_HLDefaultNames, "monster_human_assassin", "Female Assassin" );
TrieSetString( g_HLDefaultNames, "monster_barney", "Barney" );
TrieSetString( g_HLDefaultNames, "monster_gman", "Goverment Man" );
TrieSetString( g_HLDefaultNames, "monster_scientist", "Scientist" );
TrieSetString( g_HLDefaultNames, "monster_sentry", "Sentry Turret" );
TrieSetString( g_HLDefaultNames, "monster_snark", "Snark" );
TrieSetString( g_HLDefaultNames, "monster_miniturret", "Mini-Turret" );
TrieSetString( g_HLDefaultNames, "monster_turret", "Turret" );
TrieSetString( g_HLDefaultNames, "monster_apache", "Apache" );
TrieSetString( g_HLDefaultNames, "monster_osprey", "Osprey Helicopter" );
TrieSetString( g_HLDefaultNames, "monster_gargantua", "Gargantua" );
TrieSetString( g_HLDefaultNames, "monster_nihilanth", "Nihilanth" );
TrieSetString( g_HLDefaultNames, "monster_tentacle", "Tentacle" );
// HACK: since Ham_Spawn won't work, this should do as an alternative
RegisterHam( Ham_SetObjectCollisionBox, "monster_headcrab", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_babycrab", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_bullchicken", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_barnacle", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_bigmomma", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_houndeye", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_slave", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_controller", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_grunt", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_zombie", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_ichthyosaur", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_human_grunt", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_human_assassin", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_barney", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_gman", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_scientist", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_sentry", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_snark", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_miniturret", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_turret", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_apache", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_osprey", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_gargantua", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_nihilanth", "hlSpawn", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_tentacle", "hlSpawn", 1 );
RegisterHam( Ham_Killed, "player", "PlayerKilled", 1 );
}
public plugin_end()
{
TrieDestroy( g_HLDefaultNames ); // free the handle
}
public mmIRelationship( entity, other )
{
new selfClassify, otherClassify;
selfClassify = entity_get_int( entity, EV_INT_iuser4 );
otherClassify = entity_get_int( other, EV_INT_iuser4 );
if ( entity_get_int( other, EV_INT_flags ) & FL_CLIENT )
otherClassify = 2;
// Get proper relationship
SetHamReturnInteger( IRelationshipByClass( selfClassify, otherClassify ) );
return HAM_OVERRIDE;
}
public hlSpawn( entity )
{
// Why is it called 3 times? Restrict this to only once
if ( !( entity_get_int( entity, EV_INT_impulse ) & bits_MEMORY_NAMED ) )
{
// Classify not overriden?
if ( !entity_get_int( entity, EV_INT_iuser4 ) )
{
// Set default
entity_set_int( entity, EV_INT_iuser4, ExecuteHam( Ham_Classify, entity ) );
}
// Blood color not overriden?
if ( !entity_get_int( entity, EV_INT_iuser3 ) )
{
// Set default
entity_set_int( entity, EV_INT_iuser3, ExecuteHam( Ham_BloodColor, entity ) );
}
// No name set?
new szDisplayname[ 129 ];
entity_get_string( entity, EV_SZ_netname, szDisplayname, charsmax( szDisplayname ) );
if ( !strlen( szDisplayname ) )
{
// Find a default name
new szClassname[ 33 ], bool:found;
entity_get_string( entity, EV_SZ_classname, szClassname, charsmax( szClassname ) );
found = TrieGetString( g_HLDefaultNames, szClassname, szDisplayname, charsmax( szDisplayname ) );
// Use this name
entity_set_string( entity, EV_SZ_netname, ( found ? szDisplayname : "Monster" ) );
}
entity_set_int( entity, EV_INT_impulse, entity_get_int( entity, EV_INT_impulse ) | bits_MEMORY_NAMED );
}
}
stock IRelationshipByClass( classEntity, classOther )
{
if ( classEntity == -1 )
classEntity = 0; // CLASS_FORCE_NONE
new iEnemy[16][16] =
{ // NONE MACH PLYR HPASS HMIL AMIL APASS AMONST APREY APRED INSECT PLRALY PBWPN ABWPN RXPIT RXSHK
/*NONE*/ { R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO, R_NO, R_NO, R_NO, R_NO },
/*MACHINE*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL, R_DL, R_DL, R_DL, R_DL },
/*PLAYER*/ { R_NO ,R_DL ,R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_DL, R_DL, R_DL, R_DL },
/*HUMANPASSIVE*/{ R_NO ,R_FR ,R_AL ,R_AL ,R_HT ,R_DL ,R_DL ,R_HT ,R_DL ,R_DL ,R_NO ,R_AL, R_NO, R_NO, R_FR, R_FR },
/*HUMANMILITAR*/{ R_NO ,R_NO ,R_DL ,R_DL ,R_AL ,R_HT ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL, R_NO, R_NO, R_HT, R_HT },
/*ALIENMILITAR*/{ R_NO ,R_DL ,R_DL ,R_DL ,R_HT ,R_AL ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO, R_DL, R_HT },
/*ALIENPASSIVE*/{ R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO, R_NO, R_NO, R_NO, R_NO },
/*ALIENMONSTER*/{ R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_NO ,R_DL, R_NO, R_NO, R_NO, R_NO },
/*ALIENPREY */{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_NO ,R_FR ,R_NO ,R_DL, R_NO, R_NO, R_FR, R_NO },
/*ALIENPREDATO*/{ R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO ,R_NO ,R_HT ,R_NO ,R_NO ,R_DL, R_NO, R_NO, R_DL, R_DL },
/*INSECT*/ { R_NO ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR ,R_FR ,R_FR ,R_FR ,R_NO ,R_FR, R_NO, R_NO, R_NO, R_NO },
/*PLAYERALLY*/ { R_NO ,R_DL ,R_AL ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_NO, R_NO, R_DL, R_DL },
/*PBIOWEAPON*/ { R_NO ,R_NO ,R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_NO, R_NO, R_DL, R_DL, R_DL },
/*ABIOWEAPON*/ { R_NO ,R_NO ,R_DL ,R_DL ,R_DL ,R_AL ,R_NO ,R_DL ,R_DL ,R_NO ,R_NO ,R_DL, R_DL, R_NO, R_DL, R_DL },
/*RXPITDRONE*/ { R_NO ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_DL ,R_NO ,R_DL ,R_DL ,R_NO ,R_DL, R_NO, R_NO, R_AL, R_AL },
/*RXSHOCKTRP*/ { R_NO ,R_DL ,R_HT ,R_DL ,R_HT ,R_HT ,R_DL ,R_NO ,R_NO ,R_DL ,R_NO ,R_DL, R_NO, R_NO, R_AL, R_AL }
};
return iEnemy[ classEntity ][ classOther ];
}
public PlayerKilled( victim, attacker, shouldgib )
{
// don't obstruct monstermod
if ( victim == attacker )
return HAM_IGNORED;
// fix monster score
if ( entity_get_int( attacker, EV_INT_flags ) & FL_MONSTER )
entity_set_float( attacker, EV_FL_frags, entity_get_float( attacker, EV_FL_frags ) + 2 );
entity_set_edict( victim, EV_ENT_dmg_inflictor, attacker );
return HAM_IGNORED;
}

View File

@@ -0,0 +1,204 @@
#pragma semicolon 1
#include <amxmodx>
#include <engine>
#include <fakemeta>
#include <hamsandwich>
const bits_MEMORY_SOUNDLIST = ( 1 << 3 );
new Trie:m_Sounds;
public plugin_init()
{
register_plugin( "HL-MONSTER Soundlist", "1.0", "Giegue" );
/* STOP DUPLICATING CODE FFS */
RegisterHam( Ham_SetObjectCollisionBox, "monster_headcrab", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_babycrab", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_bullchicken", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_barnacle", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_bigmomma", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_houndeye", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_slave", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_controller", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_alien_grunt", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_zombie", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_ichthyosaur", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_human_grunt", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_human_assassin", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_barney", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_gman", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_scientist", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_sentry", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_snark", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_miniturret", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_turret", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_apache", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_osprey", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_gargantua", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_nihilanth", "MonsterSpawn_Post", 1 );
RegisterHam( Ham_SetObjectCollisionBox, "monster_tentacle", "MonsterSpawn_Post", 1 );
}
public plugin_end()
{
if ( m_Sounds )
TrieDestroy( m_Sounds );
}
// has to be in precache or it won't work
public plugin_precache()
{
// check individual monster soundlists
register_forward( FM_KeyValue, "ScanSL" );
}
public ScanSL( entid, kvd_handle )
{
if (is_valid_ent(entid))
{
static classname[ 33 ], keyname[ 33 ], value[ 128 ];
get_kvd( kvd_handle, KV_ClassName, classname, charsmax( classname ) );
// Monsters
if ( equal( classname, "monster_", 8 ) )
{
get_kvd( kvd_handle, KV_KeyName, keyname, charsmax( keyname ) );
get_kvd( kvd_handle, KV_Value, value, charsmax( value ) );
// Individual sound replacement
if ( equal( keyname, "soundlist" ) )
{
ProcessSoundList( entid, value );
}
return FMRES_IGNORED;
}
// Monster Makers
else if ( equal( classname, "monstermaker" ) )
{
get_kvd( kvd_handle, KV_KeyName, keyname, charsmax( keyname ) );
get_kvd( kvd_handle, KV_Value, value, charsmax( value ) );
// Children sound list
if ( equal( keyname, "soundlist" ) )
{
ProcessSoundList( entid, value );
}
return FMRES_IGNORED;
}
}
return FMRES_IGNORED;
}
public ProcessSoundList( entity, const filename[] )
{
// First time?
if ( !m_Sounds )
m_Sounds = TrieCreate();
new fullPath[ 129 ];
new mapName[ 33 ], pFile;
get_mapname( mapName, charsmax( mapName ) );
// path always starts from sound/[MAPNAME] (SC behaviour)
formatex( fullPath, charsmax( fullPath ), "sound/%s/%s", mapName, filename );
pFile = fopen( fullPath, "r" );
if ( pFile )
{
new line[ 258 ], soundSrc[ 129 ], soundDest[ 129 ];
while ( fgets( pFile, line, charsmax( line ) ) )
{
// Replace newlines
replace_all( line, charsmax( line ), "^n", "" );
// Ignore blank lines
if ( !line[ 0 ] ) continue;
// source --> destination
parse( line, soundSrc, charsmax( soundSrc ), soundDest, charsmax( soundDest ) );
// Precache destination sound
// HACK: precache_sound outside of plugin_precache
engfunc( EngFunc_PrecacheSound, soundDest );
// HACK: prepend the entityID at the beginning of the soundSrc for later identification
format( soundSrc, charsmax( soundSrc ), "%i#%s", entity, soundSrc );
TrieSetString( m_Sounds, soundSrc, soundDest );
entity_set_int( entity, EV_INT_impulse, entity_get_int( entity, EV_INT_impulse ) | bits_MEMORY_SOUNDLIST );
}
fclose( pFile );
// file could be empty
if ( TrieGetSize( m_Sounds ) )
{
register_forward( FM_EmitSound, "ReplaceSound" );
}
}
}
public ReplaceSound( entity, channel, const sample[], Float:volume, Float:attn, flags, pitch )
{
static newSound[ 129 ];
// replace monster sound?
if ( entity_get_int( entity, EV_INT_impulse ) & bits_MEMORY_SOUNDLIST )
{
// get entityID
static owner, entid;
owner = entity_get_edict( entity, EV_ENT_owner );
if ( owner )
entid = owner;
else
entid = entity;
// get sound
static searchSound[ 129 ];
formatex( searchSound, charsmax( searchSound ), "%i#%s", entid, sample );
// if found, stick to that one
if ( TrieGetString( m_Sounds, searchSound, newSound, charsmax( newSound ) ) )
{
// emit new sound and supercede this one
emit_sound( entity, channel, newSound, volume, attn, flags, pitch );
return FMRES_SUPERCEDE;
}
}
return FMRES_IGNORED;
}
/* extra_keyvalues.sma duplication */
public MonsterSpawn_Post( entity )
{
// monstermaker sets owner after monster spawn, wait next frame
set_task( 0.000001, "MakerSpawn_Post", entity );
}
public MakerSpawn_Post( entity )
{
if ( is_valid_ent( entity ) )
{
static owner;
owner = entity_get_edict( entity, EV_ENT_owner );
if ( owner )
{
// monstermaker has soundlist defined?
if ( entity_get_int( owner, EV_INT_impulse ) & bits_MEMORY_SOUNDLIST )
{
// 3 time call
if ( !( entity_get_int( entity, EV_INT_impulse ) & bits_MEMORY_SOUNDLIST ) )
{
// this monster is to use sound replacements
entity_set_int( entity, EV_INT_impulse, entity_get_int( entity, EV_INT_impulse ) | bits_MEMORY_SOUNDLIST );
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +1,52 @@
/*** /***
* *
* Copyright (c) 1999, 2000, Valve LLC. All rights reserved. * Copyright (c) 1999, 2000, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
/* crc.h */ /* crc.h */
#ifndef CRC_H #ifndef CRC_H
#define CRC_H #define CRC_H
#ifdef _WIN32 #ifdef _WIN32
#pragma once #pragma once
#endif #endif
// MD5 Hash // MD5 Hash
typedef struct typedef struct
{ {
unsigned int buf[4]; unsigned int buf[4];
unsigned int bits[2]; unsigned int bits[2];
unsigned char in[64]; unsigned char in[64];
} MD5Context_t; } MD5Context_t;
typedef unsigned long CRC32_t; typedef unsigned long CRC32_t;
void CRC32_Init(CRC32_t *pulCRC); void CRC32_Init(CRC32_t *pulCRC);
CRC32_t CRC32_Final(CRC32_t pulCRC); CRC32_t CRC32_Final(CRC32_t pulCRC);
void CRC32_ProcessBuffer(CRC32_t *pulCRC, void *p, int len); void CRC32_ProcessBuffer(CRC32_t *pulCRC, void *p, int len);
void CRC32_ProcessByte(CRC32_t *pulCRC, unsigned char ch); void CRC32_ProcessByte(CRC32_t *pulCRC, unsigned char ch);
int CRC_File(CRC32_t *crcvalue, char *pszFileName); int CRC_File(CRC32_t *crcvalue, char *pszFileName);
unsigned char COM_BlockSequenceCRCByte (unsigned char *base, int length, int sequence); unsigned char COM_BlockSequenceCRCByte (unsigned char *base, int length, int sequence);
void MD5Init(MD5Context_t *context); void MD5Init(MD5Context_t *context);
void MD5Update(MD5Context_t *context, unsigned char const *buf, void MD5Update(MD5Context_t *context, unsigned char const *buf,
unsigned int len); unsigned int len);
void MD5Final(unsigned char digest[16], MD5Context_t *context); void MD5Final(unsigned char digest[16], MD5Context_t *context);
void Transform(unsigned int buf[4], unsigned int const in[16]); void Transform(unsigned int buf[4], unsigned int const in[16]);
int MD5_Hash_File(unsigned char digest[16], char *pszFileName, int bUsefopen, int bSeed, unsigned int seed[4]); int MD5_Hash_File(unsigned char digest[16], char *pszFileName, int bUsefopen, int bSeed, unsigned int seed[4]);
char *MD5_Print(unsigned char hash[16]); char *MD5_Print(unsigned char hash[16]);
int MD5_Hash_CachedFile(unsigned char digest[16], unsigned char *pCache, int nFileSize, int bSeed, unsigned int seed[4]); int MD5_Hash_CachedFile(unsigned char digest[16], unsigned char *pCache, int nFileSize, int bSeed, unsigned int seed[4]);
int CRC_MapFile(CRC32_t *crcvalue, char *pszFileName); int CRC_MapFile(CRC32_t *crcvalue, char *pszFileName);
#endif #endif

View File

@@ -1,36 +1,36 @@
/*** /***
* *
* Copyright (c) 1999, 2000, Valve LLC. All rights reserved. * Copyright (c) 1999, 2000, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef CVARDEF_H #ifndef CVARDEF_H
#define CVARDEF_H #define CVARDEF_H
#define FCVAR_ARCHIVE (1<<0) // set to cause it to be saved to vars.rc #define FCVAR_ARCHIVE (1<<0) // set to cause it to be saved to vars.rc
#define FCVAR_USERINFO (1<<1) // changes the client's info string #define FCVAR_USERINFO (1<<1) // changes the client's info string
#define FCVAR_SERVER (1<<2) // notifies players when changed #define FCVAR_SERVER (1<<2) // notifies players when changed
#define FCVAR_EXTDLL (1<<3) // defined by external DLL #define FCVAR_EXTDLL (1<<3) // defined by external DLL
#define FCVAR_CLIENTDLL (1<<4) // defined by the client dll #define FCVAR_CLIENTDLL (1<<4) // defined by the client dll
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value #define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server. #define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
#define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). #define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log #define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
typedef struct cvar_s typedef struct cvar_s
{ {
char *name; char *name;
char *string; char *string;
int flags; int flags;
float value; float value;
struct cvar_s *next; struct cvar_s *next;
} cvar_t; } cvar_t;
#endif #endif

View File

@@ -1,193 +1,193 @@
/*** /***
* *
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved. * Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#if !defined( ENTITY_STATEH ) #if !defined( ENTITY_STATEH )
#define ENTITY_STATEH #define ENTITY_STATEH
#ifdef _WIN32 #ifdef _WIN32
#pragma once #pragma once
#endif #endif
// For entityType below // For entityType below
#define ENTITY_NORMAL (1<<0) #define ENTITY_NORMAL (1<<0)
#define ENTITY_BEAM (1<<1) #define ENTITY_BEAM (1<<1)
// Entity state is used for the baseline and for delta compression of a packet of // Entity state is used for the baseline and for delta compression of a packet of
// entities that is sent to a client. // entities that is sent to a client.
typedef struct entity_state_s entity_state_t; typedef struct entity_state_s entity_state_t;
struct entity_state_s struct entity_state_s
{ {
// Fields which are filled in by routines outside of delta compression // Fields which are filled in by routines outside of delta compression
int entityType; int entityType;
// Index into cl_entities array for this entity. // Index into cl_entities array for this entity.
int number; int number;
float msg_time; float msg_time;
// Message number last time the player/entity state was updated. // Message number last time the player/entity state was updated.
int messagenum; int messagenum;
// Fields which can be transitted and reconstructed over the network stream // Fields which can be transitted and reconstructed over the network stream
vec3_t origin; vec3_t origin;
vec3_t angles; vec3_t angles;
int modelindex; int modelindex;
int sequence; int sequence;
float frame; float frame;
int colormap; int colormap;
short skin; short skin;
short solid; short solid;
int effects; int effects;
float scale; float scale;
byte eflags; byte eflags;
// Render information // Render information
int rendermode; int rendermode;
int renderamt; int renderamt;
color24 rendercolor; color24 rendercolor;
int renderfx; int renderfx;
int movetype; int movetype;
float animtime; float animtime;
float framerate; float framerate;
int body; int body;
byte controller[4]; byte controller[4];
byte blending[4]; byte blending[4];
vec3_t velocity; vec3_t velocity;
// Send bbox down to client for use during prediction. // Send bbox down to client for use during prediction.
vec3_t mins; vec3_t mins;
vec3_t maxs; vec3_t maxs;
int aiment; int aiment;
// If owned by a player, the index of that player ( for projectiles ). // If owned by a player, the index of that player ( for projectiles ).
int owner; int owner;
// Friction, for prediction. // Friction, for prediction.
float friction; float friction;
// Gravity multiplier // Gravity multiplier
float gravity; float gravity;
// PLAYER SPECIFIC // PLAYER SPECIFIC
int team; int team;
int playerclass; int playerclass;
int health; int health;
qboolean spectator; qboolean spectator;
int weaponmodel; int weaponmodel;
int gaitsequence; int gaitsequence;
// If standing on conveyor, e.g. // If standing on conveyor, e.g.
vec3_t basevelocity; vec3_t basevelocity;
// Use the crouched hull, or the regular player hull. // Use the crouched hull, or the regular player hull.
int usehull; int usehull;
// Latched buttons last time state updated. // Latched buttons last time state updated.
int oldbuttons; int oldbuttons;
// -1 = in air, else pmove entity number // -1 = in air, else pmove entity number
int onground; int onground;
int iStepLeft; int iStepLeft;
// How fast we are falling // How fast we are falling
float flFallVelocity; float flFallVelocity;
float fov; float fov;
int weaponanim; int weaponanim;
// Parametric movement overrides // Parametric movement overrides
vec3_t startpos; vec3_t startpos;
vec3_t endpos; vec3_t endpos;
float impacttime; float impacttime;
float starttime; float starttime;
// For mods // For mods
int iuser1; int iuser1;
int iuser2; int iuser2;
int iuser3; int iuser3;
int iuser4; int iuser4;
float fuser1; float fuser1;
float fuser2; float fuser2;
float fuser3; float fuser3;
float fuser4; float fuser4;
vec3_t vuser1; vec3_t vuser1;
vec3_t vuser2; vec3_t vuser2;
vec3_t vuser3; vec3_t vuser3;
vec3_t vuser4; vec3_t vuser4;
}; };
#include "pm_info.h" #include "pm_info.h"
typedef struct clientdata_s typedef struct clientdata_s
{ {
vec3_t origin; vec3_t origin;
vec3_t velocity; vec3_t velocity;
int viewmodel; int viewmodel;
vec3_t punchangle; vec3_t punchangle;
int flags; int flags;
int waterlevel; int waterlevel;
int watertype; int watertype;
vec3_t view_ofs; vec3_t view_ofs;
float health; float health;
int bInDuck; int bInDuck;
int weapons; // remove? int weapons; // remove?
int flTimeStepSound; int flTimeStepSound;
int flDuckTime; int flDuckTime;
int flSwimTime; int flSwimTime;
int waterjumptime; int waterjumptime;
float maxspeed; float maxspeed;
float fov; float fov;
int weaponanim; int weaponanim;
int m_iId; int m_iId;
int ammo_shells; int ammo_shells;
int ammo_nails; int ammo_nails;
int ammo_cells; int ammo_cells;
int ammo_rockets; int ammo_rockets;
float m_flNextAttack; float m_flNextAttack;
int tfstate; int tfstate;
int pushmsec; int pushmsec;
int deadflag; int deadflag;
char physinfo[ MAX_PHYSINFO_STRING ]; char physinfo[ MAX_PHYSINFO_STRING ];
// For mods // For mods
int iuser1; int iuser1;
int iuser2; int iuser2;
int iuser3; int iuser3;
int iuser4; int iuser4;
float fuser1; float fuser1;
float fuser2; float fuser2;
float fuser3; float fuser3;
float fuser4; float fuser4;
vec3_t vuser1; vec3_t vuser1;
vec3_t vuser2; vec3_t vuser2;
vec3_t vuser3; vec3_t vuser3;
vec3_t vuser4; vec3_t vuser4;
} clientdata_t; } clientdata_t;
#include "weaponinfo.h" #include "weaponinfo.h"
typedef struct local_state_s typedef struct local_state_s
{ {
entity_state_t playerstate; entity_state_t playerstate;
clientdata_t client; clientdata_t client;
weapon_data_t weapondata[ 32 ]; weapon_data_t weapondata[ 32 ];
} local_state_t; } local_state_t;
#endif // !ENTITY_STATEH #endif // !ENTITY_STATEH

View File

@@ -1,47 +1,47 @@
/*** /***
* *
* Copyright (c) 1999, 2000, Valve LLC. All rights reserved. * Copyright (c) 1999, 2000, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#if !defined( EVENT_FLAGSH ) #if !defined( EVENT_FLAGSH )
#define EVENT_FLAGSH #define EVENT_FLAGSH
#ifdef _WIN32 #ifdef _WIN32
#pragma once #pragma once
#endif #endif
// Skip local host for event send. // Skip local host for event send.
#define FEV_NOTHOST (1<<0) #define FEV_NOTHOST (1<<0)
// Send the event reliably. You must specify the origin and angles and use // Send the event reliably. You must specify the origin and angles and use
// PLAYBACK_EVENT_FULL for this to work correctly on the server for anything // PLAYBACK_EVENT_FULL for this to work correctly on the server for anything
// that depends on the event origin/angles. I.e., the origin/angles are not // that depends on the event origin/angles. I.e., the origin/angles are not
// taken from the invoking edict for reliable events. // taken from the invoking edict for reliable events.
#define FEV_RELIABLE (1<<1) #define FEV_RELIABLE (1<<1)
// Don't restrict to PAS/PVS, send this event to _everybody_ on the server ( useful for stopping CHAN_STATIC // Don't restrict to PAS/PVS, send this event to _everybody_ on the server ( useful for stopping CHAN_STATIC
// sounds started by client event when client is not in PVS anymore ( hwguy in TFC e.g. ). // sounds started by client event when client is not in PVS anymore ( hwguy in TFC e.g. ).
#define FEV_GLOBAL (1<<2) #define FEV_GLOBAL (1<<2)
// If this client already has one of these events in its queue, just update the event instead of sending it as a duplicate // If this client already has one of these events in its queue, just update the event instead of sending it as a duplicate
// //
#define FEV_UPDATE (1<<3) #define FEV_UPDATE (1<<3)
// Only send to entity specified as the invoker // Only send to entity specified as the invoker
#define FEV_HOSTONLY (1<<4) #define FEV_HOSTONLY (1<<4)
// Only send if the event was created on the server. // Only send if the event was created on the server.
#define FEV_SERVER (1<<5) #define FEV_SERVER (1<<5)
// Only issue event client side ( from shared code ) // Only issue event client side ( from shared code )
#define FEV_CLIENT (1<<6) #define FEV_CLIENT (1<<6)
#endif #endif

View File

@@ -1,38 +1,38 @@
/*** /***
* *
* Copyright (c) 1999, 2000, Valve LLC. All rights reserved. * Copyright (c) 1999, 2000, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef IN_BUTTONS_H #ifndef IN_BUTTONS_H
#define IN_BUTTONS_H #define IN_BUTTONS_H
#ifdef _WIN32 #ifdef _WIN32
#pragma once #pragma once
#endif #endif
#define IN_ATTACK (1 << 0) #define IN_ATTACK (1 << 0)
#define IN_JUMP (1 << 1) #define IN_JUMP (1 << 1)
#define IN_DUCK (1 << 2) #define IN_DUCK (1 << 2)
#define IN_FORWARD (1 << 3) #define IN_FORWARD (1 << 3)
#define IN_BACK (1 << 4) #define IN_BACK (1 << 4)
#define IN_USE (1 << 5) #define IN_USE (1 << 5)
#define IN_CANCEL (1 << 6) #define IN_CANCEL (1 << 6)
#define IN_LEFT (1 << 7) #define IN_LEFT (1 << 7)
#define IN_RIGHT (1 << 8) #define IN_RIGHT (1 << 8)
#define IN_MOVELEFT (1 << 9) #define IN_MOVELEFT (1 << 9)
#define IN_MOVERIGHT (1 << 10) #define IN_MOVERIGHT (1 << 10)
#define IN_ATTACK2 (1 << 11) #define IN_ATTACK2 (1 << 11)
#define IN_RUN (1 << 12) #define IN_RUN (1 << 12)
#define IN_RELOAD (1 << 13) #define IN_RELOAD (1 << 13)
#define IN_ALT1 (1 << 14) #define IN_ALT1 (1 << 14)
#define IN_SCORE (1 << 15) // Used by client.dll for when scoreboard is held down #define IN_SCORE (1 << 15) // Used by client.dll for when scoreboard is held down
#endif // IN_BUTTONS_H #endif // IN_BUTTONS_H

View File

@@ -1,15 +1,15 @@
//========= Copyright <20> 1996-2001, Valve LLC, All rights reserved. ============ //========= Copyright <20> 1996-2001, Valve LLC, All rights reserved. ============
// //
// Purpose: // Purpose:
// //
// $NoKeywords: $ // $NoKeywords: $
//============================================================================= //=============================================================================
#ifndef INC_NOWIN_H #ifndef INC_NOWIN_H
#define INC_NOWIN_H #define INC_NOWIN_H
#ifndef _WIN32 #ifndef _WIN32
#include <unistd.h> #include <unistd.h>
#endif //!_WIN32 #endif //!_WIN32
#endif //INC_NOWIN_H #endif //INC_NOWIN_H

View File

@@ -1,29 +1,29 @@
/*** /***
* *
* Copyright (c) 1999, 2000, Valve LLC. All rights reserved. * Copyright (c) 1999, 2000, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#if !defined( STUDIO_EVENTH ) #if !defined( STUDIO_EVENTH )
#define STUDIO_EVENTH #define STUDIO_EVENTH
#ifdef _WIN32 #ifdef _WIN32
#pragma once #pragma once
#endif #endif
typedef struct mstudioevent_s typedef struct mstudioevent_s
{ {
int frame; int frame;
int event; int event;
int type; int type;
char options[64]; char options[64];
} mstudioevent_t; } mstudioevent_t;
#endif // STUDIO_EVENTH #endif // STUDIO_EVENTH

14
src/dlls/.gitignore vendored
View File

@@ -1,5 +1,9 @@
msgs/ Release/
opt.*/ Debug/
debug.*/ msgs/
*.o opt.*/
*.so debug.*/
*.o
*.so
*.suo
*.sdf

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
CPP = g++-7 CPP = g++
BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -m32 BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -m32 -fPIC
OPTFLAGS = -O2 OPTFLAGS = -O2
CPPFLAGS = ${BASEFLAGS} ${OPTFLAGS} -w -I. -I../engine -I../common -I../pm_shared -I../metamod CPPFLAGS = ${BASEFLAGS} ${OPTFLAGS} -w -I. -I../engine -I../common -I../pm_shared -I../metamod
@@ -17,10 +17,13 @@ OBJ = \
controller.o \ controller.o \
defaultai.o \ defaultai.o \
dllapi.o \ dllapi.o \
explode.o \
effects.o \ effects.o \
explode.o \
flyingmonster.o \
gargantua.o \ gargantua.o \
ggrenade.o \ ggrenade.o \
globalreplace.o \
gonome.o \
h_ai.o \ h_ai.o \
h_export.o \ h_export.o \
hassassin.o \ hassassin.o \
@@ -28,21 +31,37 @@ OBJ = \
hgrunt.o \ hgrunt.o \
hornet.o \ hornet.o \
houndeye.o \ houndeye.o \
hwgrunt.o \
islave.o \ islave.o \
massn.o \
monster_api.o \ monster_api.o \
monster_config.o \ monster_config.o \
monstermaker.o \
monsters.o \ monsters.o \
monsterstate.o \ monsterstate.o \
music.o \
nodes.o \ nodes.o \
otis.o \
pitdrone.o \
rgrunt.o \
ripent.o \
scientist.o \ scientist.o \
setcvar.o \
shock.o \
shockroach.o \
skill.o \ skill.o \
sound.o \ sound.o \
sporegrenade.o \
squeakgrenade.o \ squeakgrenade.o \
strooper.o \
stukabat.o \
subs.o \ subs.o \
talkmonster.o \ talkmonster.o \
turret.o \ turret.o \
util.o \ util.o \
voltigore.o \
weapons.o \ weapons.o \
xenmaker.o \
zombie.o zombie.o
monster_mm_i386.so: ${OBJ} monster_mm_i386.so: ${OBJ}

View File

@@ -1,109 +1,109 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef ACTIVITY_H #ifndef ACTIVITY_H
#define ACTIVITY_H #define ACTIVITY_H
typedef enum { typedef enum {
ACT_RESET = 0, // Set m_Activity to this invalid value to force a reset to m_IdealActivity ACT_RESET = 0, // Set m_Activity to this invalid value to force a reset to m_IdealActivity
ACT_IDLE = 1, ACT_IDLE = 1,
ACT_GUARD, ACT_GUARD,
ACT_WALK, ACT_WALK,
ACT_RUN, ACT_RUN,
ACT_FLY, // Fly (and flap if appropriate) ACT_FLY, // Fly (and flap if appropriate)
ACT_SWIM, ACT_SWIM,
ACT_HOP, // vertical jump ACT_HOP, // vertical jump
ACT_LEAP, // long forward jump ACT_LEAP, // long forward jump
ACT_FALL, ACT_FALL,
ACT_LAND, ACT_LAND,
ACT_STRAFE_LEFT, ACT_STRAFE_LEFT,
ACT_STRAFE_RIGHT, ACT_STRAFE_RIGHT,
ACT_ROLL_LEFT, // tuck and roll, left ACT_ROLL_LEFT, // tuck and roll, left
ACT_ROLL_RIGHT, // tuck and roll, right ACT_ROLL_RIGHT, // tuck and roll, right
ACT_TURN_LEFT, // turn quickly left (stationary) ACT_TURN_LEFT, // turn quickly left (stationary)
ACT_TURN_RIGHT, // turn quickly right (stationary) ACT_TURN_RIGHT, // turn quickly right (stationary)
ACT_CROUCH, // the act of crouching down from a standing position ACT_CROUCH, // the act of crouching down from a standing position
ACT_CROUCHIDLE, // holding body in crouched position (loops) ACT_CROUCHIDLE, // holding body in crouched position (loops)
ACT_STAND, // the act of standing from a crouched position ACT_STAND, // the act of standing from a crouched position
ACT_USE, ACT_USE,
ACT_SIGNAL1, ACT_SIGNAL1,
ACT_SIGNAL2, ACT_SIGNAL2,
ACT_SIGNAL3, ACT_SIGNAL3,
ACT_TWITCH, ACT_TWITCH,
ACT_COWER, ACT_COWER,
ACT_SMALL_FLINCH, ACT_SMALL_FLINCH,
ACT_BIG_FLINCH, ACT_BIG_FLINCH,
ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK1,
ACT_RANGE_ATTACK2, ACT_RANGE_ATTACK2,
ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK1,
ACT_MELEE_ATTACK2, ACT_MELEE_ATTACK2,
ACT_RELOAD, ACT_RELOAD,
ACT_ARM, // pull out gun, for instance ACT_ARM, // pull out gun, for instance
ACT_DISARM, // reholster gun ACT_DISARM, // reholster gun
ACT_EAT, // monster chowing on a large food item (loop) ACT_EAT, // monster chowing on a large food item (loop)
ACT_DIESIMPLE, ACT_DIESIMPLE,
ACT_DIEBACKWARD, ACT_DIEBACKWARD,
ACT_DIEFORWARD, ACT_DIEFORWARD,
ACT_DIEVIOLENT, ACT_DIEVIOLENT,
ACT_BARNACLE_HIT, // barnacle tongue hits a monster ACT_BARNACLE_HIT, // barnacle tongue hits a monster
ACT_BARNACLE_PULL, // barnacle is lifting the monster ( loop ) ACT_BARNACLE_PULL, // barnacle is lifting the monster ( loop )
ACT_BARNACLE_CHOMP, // barnacle latches on to the monster ACT_BARNACLE_CHOMP, // barnacle latches on to the monster
ACT_BARNACLE_CHEW, // barnacle is holding the monster in its mouth ( loop ) ACT_BARNACLE_CHEW, // barnacle is holding the monster in its mouth ( loop )
ACT_SLEEP, ACT_SLEEP,
ACT_INSPECT_FLOOR, // for active idles, look at something on or near the floor ACT_INSPECT_FLOOR, // for active idles, look at something on or near the floor
ACT_INSPECT_WALL, // for active idles, look at something directly ahead of you ( doesn't HAVE to be a wall or on a wall ) ACT_INSPECT_WALL, // for active idles, look at something directly ahead of you ( doesn't HAVE to be a wall or on a wall )
ACT_IDLE_ANGRY, // alternate idle animation in which the monster is clearly agitated. (loop) ACT_IDLE_ANGRY, // alternate idle animation in which the monster is clearly agitated. (loop)
ACT_WALK_HURT, // limp (loop) ACT_WALK_HURT, // limp (loop)
ACT_RUN_HURT, // limp (loop) ACT_RUN_HURT, // limp (loop)
ACT_HOVER, // Idle while in flight ACT_HOVER, // Idle while in flight
ACT_GLIDE, // Fly (don't flap) ACT_GLIDE, // Fly (don't flap)
ACT_FLY_LEFT, // Turn left in flight ACT_FLY_LEFT, // Turn left in flight
ACT_FLY_RIGHT, // Turn right in flight ACT_FLY_RIGHT, // Turn right in flight
ACT_DETECT_SCENT, // this means the monster smells a scent carried by the air ACT_DETECT_SCENT, // this means the monster smells a scent carried by the air
ACT_SNIFF, // this is the act of actually sniffing an item in front of the monster ACT_SNIFF, // this is the act of actually sniffing an item in front of the monster
ACT_BITE, // some large monsters can eat small things in one bite. This plays one time, EAT loops. ACT_BITE, // some large monsters can eat small things in one bite. This plays one time, EAT loops.
ACT_THREAT_DISPLAY, // without attacking, monster demonstrates that it is angry. (Yell, stick out chest, etc ) ACT_THREAT_DISPLAY, // without attacking, monster demonstrates that it is angry. (Yell, stick out chest, etc )
ACT_FEAR_DISPLAY, // monster just saw something that it is afraid of ACT_FEAR_DISPLAY, // monster just saw something that it is afraid of
ACT_EXCITED, // for some reason, monster is excited. Sees something he really likes to eat, or whatever. ACT_EXCITED, // for some reason, monster is excited. Sees something he really likes to eat, or whatever.
ACT_SPECIAL_ATTACK1, // very monster specific special attacks. ACT_SPECIAL_ATTACK1, // very monster specific special attacks.
ACT_SPECIAL_ATTACK2, ACT_SPECIAL_ATTACK2,
ACT_COMBAT_IDLE, // agitated idle. ACT_COMBAT_IDLE, // agitated idle.
ACT_WALK_SCARED, ACT_WALK_SCARED,
ACT_RUN_SCARED, ACT_RUN_SCARED,
ACT_VICTORY_DANCE, // killed a player, do a victory dance. ACT_VICTORY_DANCE, // killed a player, do a victory dance.
ACT_DIE_HEADSHOT, // die, hit in head. ACT_DIE_HEADSHOT, // die, hit in head.
ACT_DIE_CHESTSHOT, // die, hit in chest ACT_DIE_CHESTSHOT, // die, hit in chest
ACT_DIE_GUTSHOT, // die, hit in gut ACT_DIE_GUTSHOT, // die, hit in gut
ACT_DIE_BACKSHOT, // die, hit in back ACT_DIE_BACKSHOT, // die, hit in back
ACT_FLINCH_HEAD, ACT_FLINCH_HEAD,
ACT_FLINCH_CHEST, ACT_FLINCH_CHEST,
ACT_FLINCH_STOMACH, ACT_FLINCH_STOMACH,
ACT_FLINCH_LEFTARM, ACT_FLINCH_LEFTARM,
ACT_FLINCH_RIGHTARM, ACT_FLINCH_RIGHTARM,
ACT_FLINCH_LEFTLEG, ACT_FLINCH_LEFTLEG,
ACT_FLINCH_RIGHTLEG, ACT_FLINCH_RIGHTLEG,
} Activity; } Activity;
typedef struct { typedef struct {
int type; int type;
char *name; char *name;
} activity_map_t; } activity_map_t;
extern activity_map_t activity_map[]; extern activity_map_t activity_map[];
#endif //ACTIVITY_H #endif //ACTIVITY_H

View File

@@ -1,97 +1,97 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#define _A( a ) { a, #a } #define _A( a ) { a, #a }
activity_map_t activity_map[] = activity_map_t activity_map[] =
{ {
_A( ACT_IDLE ), _A( ACT_IDLE ),
_A( ACT_GUARD ), _A( ACT_GUARD ),
_A( ACT_WALK ), _A( ACT_WALK ),
_A( ACT_RUN ), _A( ACT_RUN ),
_A( ACT_FLY ), _A( ACT_FLY ),
_A( ACT_SWIM ), _A( ACT_SWIM ),
_A( ACT_HOP ), _A( ACT_HOP ),
_A( ACT_LEAP ), _A( ACT_LEAP ),
_A( ACT_FALL ), _A( ACT_FALL ),
_A( ACT_LAND ), _A( ACT_LAND ),
_A( ACT_STRAFE_LEFT ), _A( ACT_STRAFE_LEFT ),
_A( ACT_STRAFE_RIGHT ), _A( ACT_STRAFE_RIGHT ),
_A( ACT_ROLL_LEFT ), _A( ACT_ROLL_LEFT ),
_A( ACT_ROLL_RIGHT ), _A( ACT_ROLL_RIGHT ),
_A( ACT_TURN_LEFT ), _A( ACT_TURN_LEFT ),
_A( ACT_TURN_RIGHT ), _A( ACT_TURN_RIGHT ),
_A( ACT_CROUCH ), _A( ACT_CROUCH ),
_A( ACT_CROUCHIDLE ), _A( ACT_CROUCHIDLE ),
_A( ACT_STAND ), _A( ACT_STAND ),
_A( ACT_USE ), _A( ACT_USE ),
_A( ACT_SIGNAL1 ), _A( ACT_SIGNAL1 ),
_A( ACT_SIGNAL2 ), _A( ACT_SIGNAL2 ),
_A( ACT_SIGNAL3 ), _A( ACT_SIGNAL3 ),
_A( ACT_TWITCH ), _A( ACT_TWITCH ),
_A( ACT_COWER ), _A( ACT_COWER ),
_A( ACT_SMALL_FLINCH ), _A( ACT_SMALL_FLINCH ),
_A( ACT_BIG_FLINCH ), _A( ACT_BIG_FLINCH ),
_A( ACT_RANGE_ATTACK1 ), _A( ACT_RANGE_ATTACK1 ),
_A( ACT_RANGE_ATTACK2 ), _A( ACT_RANGE_ATTACK2 ),
_A( ACT_MELEE_ATTACK1 ), _A( ACT_MELEE_ATTACK1 ),
_A( ACT_MELEE_ATTACK2 ), _A( ACT_MELEE_ATTACK2 ),
_A( ACT_RELOAD ), _A( ACT_RELOAD ),
_A( ACT_ARM ), _A( ACT_ARM ),
_A( ACT_DISARM ), _A( ACT_DISARM ),
_A( ACT_EAT ), _A( ACT_EAT ),
_A( ACT_DIESIMPLE ), _A( ACT_DIESIMPLE ),
_A( ACT_DIEBACKWARD ), _A( ACT_DIEBACKWARD ),
_A( ACT_DIEFORWARD ), _A( ACT_DIEFORWARD ),
_A( ACT_DIEVIOLENT ), _A( ACT_DIEVIOLENT ),
_A( ACT_BARNACLE_HIT ), _A( ACT_BARNACLE_HIT ),
_A( ACT_BARNACLE_PULL ), _A( ACT_BARNACLE_PULL ),
_A( ACT_BARNACLE_CHOMP ), _A( ACT_BARNACLE_CHOMP ),
_A( ACT_BARNACLE_CHEW ), _A( ACT_BARNACLE_CHEW ),
_A( ACT_SLEEP ), _A( ACT_SLEEP ),
_A( ACT_INSPECT_FLOOR ), _A( ACT_INSPECT_FLOOR ),
_A( ACT_INSPECT_WALL ), _A( ACT_INSPECT_WALL ),
_A( ACT_IDLE_ANGRY ), _A( ACT_IDLE_ANGRY ),
_A( ACT_WALK_HURT ), _A( ACT_WALK_HURT ),
_A( ACT_RUN_HURT ), _A( ACT_RUN_HURT ),
_A( ACT_HOVER ), _A( ACT_HOVER ),
_A( ACT_GLIDE ), _A( ACT_GLIDE ),
_A( ACT_FLY_LEFT ), _A( ACT_FLY_LEFT ),
_A( ACT_FLY_RIGHT ), _A( ACT_FLY_RIGHT ),
_A( ACT_DETECT_SCENT ), _A( ACT_DETECT_SCENT ),
_A( ACT_SNIFF ), _A( ACT_SNIFF ),
_A( ACT_BITE ), _A( ACT_BITE ),
_A( ACT_THREAT_DISPLAY ), _A( ACT_THREAT_DISPLAY ),
_A( ACT_FEAR_DISPLAY ), _A( ACT_FEAR_DISPLAY ),
_A( ACT_EXCITED ), _A( ACT_EXCITED ),
_A( ACT_SPECIAL_ATTACK1 ), _A( ACT_SPECIAL_ATTACK1 ),
_A( ACT_SPECIAL_ATTACK2 ), _A( ACT_SPECIAL_ATTACK2 ),
_A( ACT_COMBAT_IDLE ), _A( ACT_COMBAT_IDLE ),
_A( ACT_WALK_SCARED ), _A( ACT_WALK_SCARED ),
_A( ACT_RUN_SCARED ), _A( ACT_RUN_SCARED ),
_A( ACT_VICTORY_DANCE ), _A( ACT_VICTORY_DANCE ),
_A( ACT_DIE_HEADSHOT ), _A( ACT_DIE_HEADSHOT ),
_A( ACT_DIE_CHESTSHOT ), _A( ACT_DIE_CHESTSHOT ),
_A( ACT_DIE_GUTSHOT ), _A( ACT_DIE_GUTSHOT ),
_A( ACT_DIE_BACKSHOT ), _A( ACT_DIE_BACKSHOT ),
_A( ACT_FLINCH_HEAD ), _A( ACT_FLINCH_HEAD ),
_A( ACT_FLINCH_CHEST ), _A( ACT_FLINCH_CHEST ),
_A( ACT_FLINCH_STOMACH ), _A( ACT_FLINCH_STOMACH ),
_A( ACT_FLINCH_LEFTARM ), _A( ACT_FLINCH_LEFTARM ),
_A( ACT_FLINCH_RIGHTARM ), _A( ACT_FLINCH_RIGHTARM ),
_A( ACT_FLINCH_LEFTLEG ), _A( ACT_FLINCH_LEFTLEG ),
_A( ACT_FLINCH_RIGHTLEG ), _A( ACT_FLINCH_RIGHTLEG ),
0, NULL 0, NULL
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -1,306 +1,306 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
/* /*
===== monsters.cpp ======================================================== ===== monsters.cpp ========================================================
Monster-related utility code Monster-related utility code
*/ */
#include "extdll.h" #include "extdll.h"
#include "util.h" #include "util.h"
#include "cmbase.h" #include "cmbase.h"
#include "animation.h" #include "animation.h"
//========================================================= //=========================================================
// StudioFrameAdvance - advance the animation frame up to the current time // StudioFrameAdvance - advance the animation frame up to the current time
// if an flInterval is passed in, only advance animation that number of seconds // if an flInterval is passed in, only advance animation that number of seconds
//========================================================= //=========================================================
float CMBaseAnimating :: StudioFrameAdvance ( float flInterval ) float CMBaseAnimating :: StudioFrameAdvance ( float flInterval )
{ {
if (flInterval == 0.0) if (flInterval == 0.0)
{ {
flInterval = (gpGlobals->time - pev->animtime); flInterval = (gpGlobals->time - pev->animtime);
if (flInterval <= 0.001) if (flInterval <= 0.001)
{ {
pev->animtime = gpGlobals->time; pev->animtime = gpGlobals->time;
return 0.0; return 0.0;
} }
} }
if (! pev->animtime) if (! pev->animtime)
flInterval = 0.0; flInterval = 0.0;
pev->frame += flInterval * m_flFrameRate * pev->framerate; pev->frame += flInterval * m_flFrameRate * pev->framerate;
pev->animtime = gpGlobals->time; pev->animtime = gpGlobals->time;
if (pev->frame < 0.0 || pev->frame >= 256.0) if (pev->frame < 0.0 || pev->frame >= 256.0)
{ {
if (m_fSequenceLoops) if (m_fSequenceLoops)
pev->frame -= (int)(pev->frame / 256.0) * 256.0; pev->frame -= (int)(pev->frame / 256.0) * 256.0;
else else
pev->frame = (pev->frame < 0.0) ? 0 : 255; pev->frame = (pev->frame < 0.0) ? 0 : 255;
m_fSequenceFinished = TRUE; // just in case it wasn't caught in GetEvents m_fSequenceFinished = TRUE; // just in case it wasn't caught in GetEvents
} }
return flInterval; return flInterval;
} }
//========================================================= //=========================================================
// LookupActivity // LookupActivity
//========================================================= //=========================================================
int CMBaseAnimating :: LookupActivity ( int activity ) int CMBaseAnimating :: LookupActivity ( int activity )
{ {
ASSERT( activity != 0 ); ASSERT( activity != 0 );
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::LookupActivity( pmodel, pev, activity ); return ::LookupActivity( pmodel, pev, activity );
} }
//========================================================= //=========================================================
// LookupActivityHeaviest // LookupActivityHeaviest
// //
// Get activity with highest 'weight' // Get activity with highest 'weight'
// //
//========================================================= //=========================================================
int CMBaseAnimating :: LookupActivityHeaviest ( int activity ) int CMBaseAnimating :: LookupActivityHeaviest ( int activity )
{ {
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::LookupActivityHeaviest( pmodel, pev, activity ); return ::LookupActivityHeaviest( pmodel, pev, activity );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
int CMBaseAnimating :: LookupSequence ( const char *label ) int CMBaseAnimating :: LookupSequence ( const char *label )
{ {
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::LookupSequence( pmodel, label ); return ::LookupSequence( pmodel, label );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
void CMBaseAnimating :: ResetSequenceInfo ( ) void CMBaseAnimating :: ResetSequenceInfo ( )
{ {
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
GetSequenceInfo( pmodel, pev, &m_flFrameRate, &m_flGroundSpeed ); GetSequenceInfo( pmodel, pev, &m_flFrameRate, &m_flGroundSpeed );
m_fSequenceLoops = ((GetSequenceFlags() & STUDIO_LOOPING) != 0); m_fSequenceLoops = ((GetSequenceFlags() & STUDIO_LOOPING) != 0);
pev->animtime = gpGlobals->time; pev->animtime = gpGlobals->time;
pev->framerate = 1.0; pev->framerate = 1.0;
m_fSequenceFinished = FALSE; m_fSequenceFinished = FALSE;
m_flLastEventCheck = gpGlobals->time; m_flLastEventCheck = gpGlobals->time;
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
BOOL CMBaseAnimating :: GetSequenceFlags( ) BOOL CMBaseAnimating :: GetSequenceFlags( )
{ {
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::GetSequenceFlags( pmodel, pev ); return ::GetSequenceFlags( pmodel, pev );
} }
//========================================================= //=========================================================
// DispatchAnimEvents // DispatchAnimEvents
//========================================================= //=========================================================
void CMBaseAnimating :: DispatchAnimEvents ( float flInterval ) void CMBaseAnimating :: DispatchAnimEvents ( float flInterval )
{ {
MonsterEvent_t event; MonsterEvent_t event;
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
if ( !pmodel ) if ( !pmodel )
{ {
ALERT( at_aiconsole, "Gibbed monster is thinking!\n" ); ALERT( at_aiconsole, "Gibbed monster is thinking!\n" );
return; return;
} }
// FIXME: I have to do this or some events get missed, and this is probably causing the problem below // FIXME: I have to do this or some events get missed, and this is probably causing the problem below
flInterval = 0.1; flInterval = 0.1;
// FIX: this still sometimes hits events twice // FIX: this still sometimes hits events twice
float flStart = pev->frame + (m_flLastEventCheck - pev->animtime) * m_flFrameRate * pev->framerate; float flStart = pev->frame + (m_flLastEventCheck - pev->animtime) * m_flFrameRate * pev->framerate;
float flEnd = pev->frame + flInterval * m_flFrameRate * pev->framerate; float flEnd = pev->frame + flInterval * m_flFrameRate * pev->framerate;
m_flLastEventCheck = pev->animtime + flInterval; m_flLastEventCheck = pev->animtime + flInterval;
m_fSequenceFinished = FALSE; m_fSequenceFinished = FALSE;
if (flEnd >= 256 || flEnd <= 0.0) if (flEnd >= 256 || flEnd <= 0.0)
m_fSequenceFinished = TRUE; m_fSequenceFinished = TRUE;
int index = 0; int index = 0;
while ( (index = GetAnimationEvent( pmodel, pev, &event, flStart, flEnd, index ) ) != 0 ) while ( (index = GetAnimationEvent( pmodel, pev, &event, flStart, flEnd, index ) ) != 0 )
{ {
HandleAnimEvent( &event ); HandleAnimEvent( &event );
} }
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
float CMBaseAnimating :: SetBoneController ( int iController, float flValue ) float CMBaseAnimating :: SetBoneController ( int iController, float flValue )
{ {
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
return SetController( pmodel, pev, iController, flValue ); return SetController( pmodel, pev, iController, flValue );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
void CMBaseAnimating :: InitBoneControllers ( void ) void CMBaseAnimating :: InitBoneControllers ( void )
{ {
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
SetController( pmodel, pev, 0, 0.0 ); SetController( pmodel, pev, 0, 0.0 );
SetController( pmodel, pev, 1, 0.0 ); SetController( pmodel, pev, 1, 0.0 );
SetController( pmodel, pev, 2, 0.0 ); SetController( pmodel, pev, 2, 0.0 );
SetController( pmodel, pev, 3, 0.0 ); SetController( pmodel, pev, 3, 0.0 );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
float CMBaseAnimating :: SetBlending ( int iBlender, float flValue ) float CMBaseAnimating :: SetBlending ( int iBlender, float flValue )
{ {
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
return ::SetBlending( pmodel, pev, iBlender, flValue ); return ::SetBlending( pmodel, pev, iBlender, flValue );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
void CMBaseAnimating :: GetBonePosition ( int iBone, Vector &origin, Vector &angles ) void CMBaseAnimating :: GetBonePosition ( int iBone, Vector &origin, Vector &angles )
{ {
GET_BONE_POSITION( ENT(pev), iBone, origin, angles ); GET_BONE_POSITION( ENT(pev), iBone, origin, angles );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
void CMBaseAnimating :: GetAttachment ( int iAttachment, Vector &origin, Vector &angles ) void CMBaseAnimating :: GetAttachment ( int iAttachment, Vector &origin, Vector &angles )
{ {
GET_ATTACHMENT( ENT(pev), iAttachment, origin, angles ); GET_ATTACHMENT( ENT(pev), iAttachment, origin, angles );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
int CMBaseAnimating :: FindTransition( int iEndingSequence, int iGoalSequence, int *piDir ) int CMBaseAnimating :: FindTransition( int iEndingSequence, int iGoalSequence, int *piDir )
{ {
void *pmodel = GET_MODEL_PTR( ENT(pev) ); void *pmodel = GET_MODEL_PTR( ENT(pev) );
if (piDir == NULL) if (piDir == NULL)
{ {
int iDir; int iDir;
int sequence = ::FindTransition( pmodel, iEndingSequence, iGoalSequence, &iDir ); int sequence = ::FindTransition( pmodel, iEndingSequence, iGoalSequence, &iDir );
if (iDir != 1) if (iDir != 1)
return -1; return -1;
else else
return sequence; return sequence;
} }
return ::FindTransition( pmodel, iEndingSequence, iGoalSequence, piDir ); return ::FindTransition( pmodel, iEndingSequence, iGoalSequence, piDir );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
void CMBaseAnimating :: GetAutomovement( Vector &origin, Vector &angles, float flInterval ) void CMBaseAnimating :: GetAutomovement( Vector &origin, Vector &angles, float flInterval )
{ {
} }
void CMBaseAnimating :: SetBodygroup( int iGroup, int iValue ) void CMBaseAnimating :: SetBodygroup( int iGroup, int iValue )
{ {
::SetBodygroup( GET_MODEL_PTR( ENT(pev) ), pev, iGroup, iValue ); ::SetBodygroup( GET_MODEL_PTR( ENT(pev) ), pev, iGroup, iValue );
} }
int CMBaseAnimating :: GetBodygroup( int iGroup ) int CMBaseAnimating :: GetBodygroup( int iGroup )
{ {
return ::GetBodygroup( GET_MODEL_PTR( ENT(pev) ), pev, iGroup ); return ::GetBodygroup( GET_MODEL_PTR( ENT(pev) ), pev, iGroup );
} }
int CMBaseAnimating :: ExtractBbox( int sequence, float *mins, float *maxs ) int CMBaseAnimating :: ExtractBbox( int sequence, float *mins, float *maxs )
{ {
return ::ExtractBbox( GET_MODEL_PTR( ENT(pev) ), sequence, mins, maxs ); return ::ExtractBbox( GET_MODEL_PTR( ENT(pev) ), sequence, mins, maxs );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
void CMBaseAnimating :: SetSequenceBox( void ) void CMBaseAnimating :: SetSequenceBox( void )
{ {
Vector mins, maxs; Vector mins, maxs;
// Get sequence bbox // Get sequence bbox
if ( ExtractBbox( pev->sequence, mins, maxs ) ) if ( ExtractBbox( pev->sequence, mins, maxs ) )
{ {
// expand box for rotation // expand box for rotation
// find min / max for rotations // find min / max for rotations
float yaw = pev->angles.y * (M_PI / 180.0); float yaw = pev->angles.y * (M_PI / 180.0);
Vector xvector, yvector; Vector xvector, yvector;
xvector.x = cos(yaw); xvector.x = cos(yaw);
xvector.y = sin(yaw); xvector.y = sin(yaw);
yvector.x = -sin(yaw); yvector.x = -sin(yaw);
yvector.y = cos(yaw); yvector.y = cos(yaw);
Vector bounds[2]; Vector bounds[2];
bounds[0] = mins; bounds[0] = mins;
bounds[1] = maxs; bounds[1] = maxs;
Vector rmin( 9999, 9999, 9999 ); Vector rmin( 9999, 9999, 9999 );
Vector rmax( -9999, -9999, -9999 ); Vector rmax( -9999, -9999, -9999 );
Vector base, transformed; Vector base, transformed;
for (int i = 0; i <= 1; i++ ) for (int i = 0; i <= 1; i++ )
{ {
base.x = bounds[i].x; base.x = bounds[i].x;
for ( int j = 0; j <= 1; j++ ) for ( int j = 0; j <= 1; j++ )
{ {
base.y = bounds[j].y; base.y = bounds[j].y;
for ( int k = 0; k <= 1; k++ ) for ( int k = 0; k <= 1; k++ )
{ {
base.z = bounds[k].z; base.z = bounds[k].z;
// transform the point // transform the point
transformed.x = xvector.x*base.x + yvector.x*base.y; transformed.x = xvector.x*base.x + yvector.x*base.y;
transformed.y = xvector.y*base.x + yvector.y*base.y; transformed.y = xvector.y*base.x + yvector.y*base.y;
transformed.z = base.z; transformed.z = base.z;
if (transformed.x < rmin.x) if (transformed.x < rmin.x)
rmin.x = transformed.x; rmin.x = transformed.x;
if (transformed.x > rmax.x) if (transformed.x > rmax.x)
rmax.x = transformed.x; rmax.x = transformed.x;
if (transformed.y < rmin.y) if (transformed.y < rmin.y)
rmin.y = transformed.y; rmin.y = transformed.y;
if (transformed.y > rmax.y) if (transformed.y > rmax.y)
rmax.y = transformed.y; rmax.y = transformed.y;
if (transformed.z < rmin.z) if (transformed.z < rmin.z)
rmin.z = transformed.z; rmin.z = transformed.z;
if (transformed.z > rmax.z) if (transformed.z > rmax.z)
rmax.z = transformed.z; rmax.z = transformed.z;
} }
} }
} }
rmin.z = 0; rmin.z = 0;
rmax.z = rmin.z + 1; rmax.z = rmin.z + 1;
UTIL_SetSize( pev, rmin, rmax ); UTIL_SetSize( pev, rmin, rmax );
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,47 +1,47 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef ANIMATION_H #ifndef ANIMATION_H
#define ANIMATION_H #define ANIMATION_H
#define ACTIVITY_NOT_AVAILABLE -1 #define ACTIVITY_NOT_AVAILABLE -1
#ifndef MONSTEREVENT_H #ifndef MONSTEREVENT_H
#include "monsterevent.h" #include "monsterevent.h"
#endif #endif
extern int IsSoundEvent( int eventNumber ); extern int IsSoundEvent( int eventNumber );
int LookupActivity( void *pmodel, entvars_t *pev, int activity ); int LookupActivity( void *pmodel, entvars_t *pev, int activity );
int LookupActivityHeaviest( void *pmodel, entvars_t *pev, int activity ); int LookupActivityHeaviest( void *pmodel, entvars_t *pev, int activity );
int LookupSequence( void *pmodel, const char *label ); int LookupSequence( void *pmodel, const char *label );
void GetSequenceInfo( void *pmodel, entvars_t *pev, float *pflFrameRate, float *pflGroundSpeed ); void GetSequenceInfo( void *pmodel, entvars_t *pev, float *pflFrameRate, float *pflGroundSpeed );
int GetSequenceFlags( void *pmodel, entvars_t *pev ); int GetSequenceFlags( void *pmodel, entvars_t *pev );
int LookupAnimationEvents( void *pmodel, entvars_t *pev, float flStart, float flEnd ); int LookupAnimationEvents( void *pmodel, entvars_t *pev, float flStart, float flEnd );
float SetController( void *pmodel, entvars_t *pev, int iController, float flValue ); float SetController( void *pmodel, entvars_t *pev, int iController, float flValue );
float SetBlending( void *pmodel, entvars_t *pev, int iBlender, float flValue ); float SetBlending( void *pmodel, entvars_t *pev, int iBlender, float flValue );
void GetEyePosition( void *pmodel, float *vecEyePosition ); void GetEyePosition( void *pmodel, float *vecEyePosition );
void SequencePrecache( void *pmodel, const char *pSequenceName ); void SequencePrecache( void *pmodel, const char *pSequenceName );
int FindTransition( void *pmodel, int iEndingAnim, int iGoalAnim, int *piDir ); int FindTransition( void *pmodel, int iEndingAnim, int iGoalAnim, int *piDir );
void SetBodygroup( void *pmodel, entvars_t *pev, int iGroup, int iValue ); void SetBodygroup( void *pmodel, entvars_t *pev, int iGroup, int iValue );
int GetBodygroup( void *pmodel, entvars_t *pev, int iGroup ); int GetBodygroup( void *pmodel, entvars_t *pev, int iGroup );
int GetAnimationEvent( void *pmodel, entvars_t *pev, MonsterEvent_t *pMonsterEvent, float flStart, float flEnd, int index ); int GetAnimationEvent( void *pmodel, entvars_t *pev, MonsterEvent_t *pMonsterEvent, float flStart, float flEnd, int index );
int ExtractBbox( void *pmodel, int sequence, float *mins, float *maxs ); int ExtractBbox( void *pmodel, int sequence, float *mins, float *maxs );
// From /engine/studio.h // From /engine/studio.h
#define STUDIO_LOOPING 0x0001 #define STUDIO_LOOPING 0x0001
#endif //ANIMATION_H #endif //ANIMATION_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +1,46 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
// //
// cdll_dll.h // cdll_dll.h
// this file is included by both the game-dll and the client-dll, // this file is included by both the game-dll and the client-dll,
#ifndef CDLL_DLL_H #ifndef CDLL_DLL_H
#define CDLL_DLL_H #define CDLL_DLL_H
#define MAX_WEAPONS 32 // ??? #define MAX_WEAPONS 32 // ???
#define MAX_WEAPON_SLOTS 5 // hud item selection slots #define MAX_WEAPON_SLOTS 5 // hud item selection slots
#define MAX_ITEM_TYPES 6 // hud item selection slots #define MAX_ITEM_TYPES 6 // hud item selection slots
#define MAX_ITEMS 5 // hard coded item types #define MAX_ITEMS 5 // hard coded item types
#define HIDEHUD_WEAPONS ( 1<<0 ) #define HIDEHUD_WEAPONS ( 1<<0 )
#define HIDEHUD_FLASHLIGHT ( 1<<1 ) #define HIDEHUD_FLASHLIGHT ( 1<<1 )
#define HIDEHUD_ALL ( 1<<2 ) #define HIDEHUD_ALL ( 1<<2 )
#define HIDEHUD_HEALTH ( 1<<3 ) #define HIDEHUD_HEALTH ( 1<<3 )
#define MAX_AMMO_TYPES 32 // ??? #define MAX_AMMO_TYPES 32 // ???
#define MAX_AMMO_SLOTS 32 // not really slots #define MAX_AMMO_SLOTS 32 // not really slots
#define HUD_PRINTNOTIFY 1 #define HUD_PRINTNOTIFY 1
#define HUD_PRINTCONSOLE 2 #define HUD_PRINTCONSOLE 2
#define HUD_PRINTTALK 3 #define HUD_PRINTTALK 3
#define HUD_PRINTCENTER 4 #define HUD_PRINTCENTER 4
#define WEAPON_SUIT 31 #define WEAPON_SUIT 31
#endif #endif

View File

@@ -1,306 +1,317 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#include "extdll.h" #include "extdll.h"
#include "util.h" #include "util.h"
#include "cmbase.h" #include "cmbase.h"
#include "decals.h" #include "decals.h"
extern Vector VecBModelOrigin( entvars_t* pevBModel ); void EntvarsKeyvalue( entvars_t *pev, KeyValueData *pkvd );
extern DLL_GLOBAL Vector g_vecAttackDir;
extern Vector VecBModelOrigin( entvars_t* pevBModel );
edict_t * EHANDLE::Get( void ) extern DLL_GLOBAL Vector g_vecAttackDir;
{
if (m_pent) edict_t * EHANDLE::Get( void )
{ {
if (m_pent->serialnumber == m_serialnumber) if (m_pent)
return m_pent; {
else if (m_pent->serialnumber == m_serialnumber)
return NULL; return m_pent;
} else
return NULL; return NULL;
}; }
return NULL;
edict_t * EHANDLE::Set( edict_t *pent ) };
{
m_pent = pent; edict_t * EHANDLE::Set( edict_t *pent )
if (pent) {
m_serialnumber = m_pent->serialnumber; m_pent = pent;
return pent; if (pent)
}; m_serialnumber = m_pent->serialnumber;
return pent;
};
EHANDLE :: operator edict_t *()
{
return Get( ); EHANDLE :: operator edict_t *()
}; {
return Get( );
};
edict_t * EHANDLE :: operator = (edict_t *pEntity)
{
if (pEntity) edict_t * EHANDLE :: operator = (edict_t *pEntity)
{ {
m_pent = pEntity; if (pEntity)
if (m_pent) {
m_serialnumber = m_pent->serialnumber; m_pent = pEntity;
} if (m_pent)
else m_serialnumber = m_pent->serialnumber;
{ }
m_pent = NULL; else
m_serialnumber = 0; {
} m_pent = NULL;
return pEntity; m_serialnumber = 0;
} }
return pEntity;
}
edict_t * EHANDLE :: operator -> ()
{
return Get( ); edict_t * EHANDLE :: operator -> ()
} {
return Get( );
}
void *CMBaseEntity::operator new( size_t stAllocateBlock )
{
void *mem = ::operator new( stAllocateBlock ); void *CMBaseEntity::operator new( size_t stAllocateBlock )
memset( mem, 0, stAllocateBlock ); {
return mem; void *mem = ::operator new( stAllocateBlock );
} memset( mem, 0, stAllocateBlock );
return mem;
}
edict_t *CMBaseEntity::CreateEntity(char *classname)
{
int istr = MAKE_STRING(classname); edict_t *CMBaseEntity::CreateEntity(char *classname)
{
edict_t *pent = CREATE_NAMED_ENTITY(istr); int istr = MAKE_STRING(classname);
if ( FNullEnt( pent ) ) edict_t *pent = CREATE_NAMED_ENTITY(istr);
return NULL;
if ( FNullEnt( pent ) )
pev = VARS(pent); return NULL;
pev->movetype = MOVETYPE_NONE; pev = VARS(pent);
pev->solid = SOLID_NOT;
pev->flags = 0; pev->movetype = MOVETYPE_NONE;
pev->solid = SOLID_NOT;
m_pfnThink = NULL; pev->flags = 0;
m_pfnTouch = NULL;
m_pfnUse = NULL; m_pfnThink = NULL;
m_pfnBlocked = NULL; m_pfnTouch = NULL;
m_pfnUse = NULL;
pev->euser4 = (edict_t *)this; m_pfnBlocked = NULL;
return pent; pev->euser4 = (edict_t *)this;
}
return pent;
// give health }
int CMBaseEntity :: TakeHealth( float flHealth, int bitsDamageType )
{ // process entvar keyvalue
if (!pev->takedamage) void CMBaseEntity :: KeyValue( KeyValueData* pkvd )
return 0; {
if ( !pev || !pkvd )
// heal return;
if ( pev->health >= pev->max_health )
return 0; EntvarsKeyvalue( pev, pkvd );
}
pev->health += flHealth;
// give health
if (pev->health > pev->max_health) int CMBaseEntity :: TakeHealth( float flHealth, int bitsDamageType )
pev->health = pev->max_health; {
if (!pev->takedamage)
return 1; return 0;
}
// heal
// inflict damage on this entity. bitsDamageType indicates type of damage inflicted, ie: DMG_CRUSH if ( pev->health >= pev->max_health )
return 0;
int CMBaseEntity :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType )
{ pev->health += flHealth;
Vector vecTemp;
if (pev->health > pev->max_health)
if (!pev->takedamage) pev->health = pev->max_health;
return 0;
return 1;
// UNDONE: some entity types may be immune or resistant to some bitsDamageType }
// if Attacker == Inflictor, the attack was a melee or other instant-hit attack. // inflict damage on this entity. bitsDamageType indicates type of damage inflicted, ie: DMG_CRUSH
// (that is, no actual entity projectile was involved in the attack so use the shooter's origin).
if ( pevAttacker == pevInflictor ) int CMBaseEntity :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType )
{ {
vecTemp = pevInflictor->origin - ( VecBModelOrigin(pev) ); Vector vecTemp;
}
else if (!pev->takedamage)
// an actual missile was involved. return 0;
{
vecTemp = pevInflictor->origin - ( VecBModelOrigin(pev) ); // UNDONE: some entity types may be immune or resistant to some bitsDamageType
}
// if Attacker == Inflictor, the attack was a melee or other instant-hit attack.
// this global is still used for glass and other non-monster killables, along with decals. // (that is, no actual entity projectile was involved in the attack so use the shooter's origin).
g_vecAttackDir = vecTemp.Normalize(); if ( pevAttacker == pevInflictor )
{
// save damage based on the target's armor level vecTemp = pevInflictor->origin - ( VecBModelOrigin(pev) );
}
// figure momentum add (don't let hurt brushes or other triggers move player) else
if ((!FNullEnt(pevInflictor)) && (pev->movetype == MOVETYPE_WALK || pev->movetype == MOVETYPE_STEP) && (pevAttacker->solid != SOLID_TRIGGER) ) // an actual missile was involved.
{ {
Vector vecDir = pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5; vecTemp = pevInflictor->origin - ( VecBModelOrigin(pev) );
vecDir = vecDir.Normalize(); }
float flForce = flDamage * ((32 * 32 * 72.0) / (pev->size.x * pev->size.y * pev->size.z)) * 5; // this global is still used for glass and other non-monster killables, along with decals.
g_vecAttackDir = vecTemp.Normalize();
if (flForce > 1000.0)
flForce = 1000.0; // save damage based on the target's armor level
pev->velocity = pev->velocity + vecDir * flForce;
} // figure momentum add (don't let hurt brushes or other triggers move player)
if ((!FNullEnt(pevInflictor)) && (pev->movetype == MOVETYPE_WALK || pev->movetype == MOVETYPE_STEP) && (pevAttacker->solid != SOLID_TRIGGER) )
// do the damage {
pev->health -= flDamage; Vector vecDir = pev->origin - (pevInflictor->absmin + pevInflictor->absmax) * 0.5;
if (pev->health <= 0) vecDir = vecDir.Normalize();
{
Killed( pevAttacker, GIB_NORMAL ); float flForce = flDamage * ((32 * 32 * 72.0) / (pev->size.x * pev->size.y * pev->size.z)) * 5;
return 0;
} if (flForce > 1000.0)
flForce = 1000.0;
return 1; pev->velocity = pev->velocity + vecDir * flForce;
} }
// do the damage
void CMBaseEntity :: Killed( entvars_t *pevAttacker, int iGib ) pev->health -= flDamage;
{ if (pev->health <= 0)
pev->takedamage = DAMAGE_NO; {
pev->deadflag = DEAD_DEAD; Killed( pevAttacker, GIB_NORMAL );
UTIL_Remove( this->edict() ); return 0;
} }
return 1;
// Initialize absmin & absmax to the appropriate box }
void SetObjectCollisionBox( entvars_t *pev )
{
if ( (pev->solid == SOLID_BSP) && void CMBaseEntity :: Killed( entvars_t *pevAttacker, int iGib )
(pev->angles.x || pev->angles.y|| pev->angles.z) ) {
{ // expand for rotation pev->takedamage = DAMAGE_NO;
float max, v; pev->deadflag = DEAD_DEAD;
int i; UTIL_Remove( this->edict() );
}
max = 0;
for (i=0 ; i<3 ; i++)
{ // Initialize absmin & absmax to the appropriate box
v = fabs( ((float *)pev->mins)[i]); void SetObjectCollisionBox( entvars_t *pev )
if (v > max) {
max = v; if ( (pev->solid == SOLID_BSP) &&
v = fabs( ((float *)pev->maxs)[i]); (pev->angles.x || pev->angles.y|| pev->angles.z) )
if (v > max) { // expand for rotation
max = v; float max, v;
} int i;
for (i=0 ; i<3 ; i++)
{ max = 0;
((float *)pev->absmin)[i] = ((float *)pev->origin)[i] - max; for (i=0 ; i<3 ; i++)
((float *)pev->absmax)[i] = ((float *)pev->origin)[i] + max; {
} v = fabs( ((float *)pev->mins)[i]);
} if (v > max)
else max = v;
{ v = fabs( ((float *)pev->maxs)[i]);
pev->absmin = pev->origin + pev->mins; if (v > max)
pev->absmax = pev->origin + pev->maxs; max = v;
} }
for (i=0 ; i<3 ; i++)
pev->absmin.x -= 1; {
pev->absmin.y -= 1; ((float *)pev->absmin)[i] = ((float *)pev->origin)[i] - max;
pev->absmin.z -= 1; ((float *)pev->absmax)[i] = ((float *)pev->origin)[i] + max;
pev->absmax.x += 1; }
pev->absmax.y += 1; }
pev->absmax.z += 1; else
} {
pev->absmin = pev->origin + pev->mins;
pev->absmax = pev->origin + pev->maxs;
void CMBaseEntity::SetObjectCollisionBox( void ) }
{
::SetObjectCollisionBox( pev ); pev->absmin.x -= 1;
} pev->absmin.y -= 1;
pev->absmin.z -= 1;
pev->absmax.x += 1;
int CMBaseEntity :: Intersects( CMBaseEntity *pOther ) pev->absmax.y += 1;
{ pev->absmax.z += 1;
if ( pOther->pev->absmin.x > pev->absmax.x || }
pOther->pev->absmin.y > pev->absmax.y ||
pOther->pev->absmin.z > pev->absmax.z ||
pOther->pev->absmax.x < pev->absmin.x || void CMBaseEntity::SetObjectCollisionBox( void )
pOther->pev->absmax.y < pev->absmin.y || {
pOther->pev->absmax.z < pev->absmin.z ) ::SetObjectCollisionBox( pev );
return 0; }
return 1;
}
int CMBaseEntity :: Intersects( CMBaseEntity *pOther )
void CMBaseEntity :: MakeDormant( void ) {
{ if ( pOther->pev->absmin.x > pev->absmax.x ||
SetBits( pev->flags, FL_DORMANT ); pOther->pev->absmin.y > pev->absmax.y ||
pOther->pev->absmin.z > pev->absmax.z ||
// Don't touch pOther->pev->absmax.x < pev->absmin.x ||
pev->solid = SOLID_NOT; pOther->pev->absmax.y < pev->absmin.y ||
// Don't move pOther->pev->absmax.z < pev->absmin.z )
pev->movetype = MOVETYPE_NONE; return 0;
// Don't draw return 1;
SetBits( pev->effects, EF_NODRAW ); }
// Don't think
pev->nextthink = 0; void CMBaseEntity :: MakeDormant( void )
// Relink {
UTIL_SetOrigin( pev, pev->origin ); SetBits( pev->flags, FL_DORMANT );
}
// Don't touch
int CMBaseEntity :: IsDormant( void ) pev->solid = SOLID_NOT;
{ // Don't move
return FBitSet( pev->flags, FL_DORMANT ); pev->movetype = MOVETYPE_NONE;
} // Don't draw
SetBits( pev->effects, EF_NODRAW );
BOOL CMBaseEntity :: IsInWorld( void ) // Don't think
{ pev->nextthink = 0;
// position // Relink
if (pev->origin.x >= 4096) return FALSE; UTIL_SetOrigin( pev, pev->origin );
if (pev->origin.y >= 4096) return FALSE; }
if (pev->origin.z >= 4096) return FALSE;
if (pev->origin.x <= -4096) return FALSE; int CMBaseEntity :: IsDormant( void )
if (pev->origin.y <= -4096) return FALSE; {
if (pev->origin.z <= -4096) return FALSE; return FBitSet( pev->flags, FL_DORMANT );
// speed }
if (pev->velocity.x >= 2000) return FALSE;
if (pev->velocity.y >= 2000) return FALSE; BOOL CMBaseEntity :: IsInWorld( void )
if (pev->velocity.z >= 2000) return FALSE; {
if (pev->velocity.x <= -2000) return FALSE; // position
if (pev->velocity.y <= -2000) return FALSE; if (pev->origin.x >= 4096) return FALSE;
if (pev->velocity.z <= -2000) return FALSE; if (pev->origin.y >= 4096) return FALSE;
if (pev->origin.z >= 4096) return FALSE;
return TRUE; if (pev->origin.x <= -4096) return FALSE;
} if (pev->origin.y <= -4096) return FALSE;
if (pev->origin.z <= -4096) return FALSE;
int CMBaseEntity::ShouldToggle( USE_TYPE useType, BOOL currentState ) // speed
{ if (pev->velocity.x >= 2000) return FALSE;
if ( useType != USE_TOGGLE && useType != USE_SET ) if (pev->velocity.y >= 2000) return FALSE;
{ if (pev->velocity.z >= 2000) return FALSE;
if ( (currentState && useType == USE_ON) || (!currentState && useType == USE_OFF) ) if (pev->velocity.x <= -2000) return FALSE;
return 0; if (pev->velocity.y <= -2000) return FALSE;
} if (pev->velocity.z <= -2000) return FALSE;
return 1;
} return TRUE;
}
int CMBaseEntity :: DamageDecal( int bitsDamageType ) int CMBaseEntity::ShouldToggle( USE_TYPE useType, BOOL currentState )
{ {
if ( pev->rendermode == kRenderTransAlpha ) if ( useType != USE_TOGGLE && useType != USE_SET )
return -1; {
if ( (currentState && useType == USE_ON) || (!currentState && useType == USE_OFF) )
if ( pev->rendermode != kRenderNormal ) return 0;
return DECAL_BPROOF1; }
return 1;
return DECAL_GUNSHOT1 + RANDOM_LONG(0,4); }
}
int CMBaseEntity :: DamageDecal( int bitsDamageType )
{
if ( pev->rendermode == kRenderTransAlpha )
return -1;
if ( pev->rendermode != kRenderNormal )
return DECAL_BPROOF1;
return DECAL_GUNSHOT1 + RANDOM_LONG(0,4);
}

File diff suppressed because it is too large Load Diff

104
src/dlls/cmbaseextra.h Normal file
View File

@@ -0,0 +1,104 @@
#ifndef BASEEXTRA_H
#define BASEEXTRA_H
// any extra entities created in this project that aren't
// monsters will go here
//=========================================================
// MonsterMaker - this ent creates monsters during the game.
//=========================================================
class CMMonsterMaker : public CMBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void KeyValue( KeyValueData* pkvd);
void EXPORT ToggleUse ( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value );
void EXPORT CyclicUse ( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value );
void EXPORT MakerThink ( void );
void DeathNotice ( entvars_t *pevChild );// monster maker children use this to tell the monster maker that they have died.
void MakeMonster( void );
int m_iMonsterIndex;// index of the monster(s) that will be created.
string_t m_iszCustomModel;// custom model that the monster will use.
int m_iMonsterBlood;//blood color of spawned monsters.
int m_cNumMonsters;// max number of monsters this ent can create
int m_iMaxLiveChildren;// max number of monsters that this maker may have out at one time.
int m_cLiveChildren;// how many monsters made by this monster maker that are currently alive
float m_flGround; // z coord of the ground under me, used to make sure no monsters are under the maker when it drops a new child
BOOL m_fActive;
BOOL m_fFadeChildren;// should we make the children fadeout?
};
//=========================================================
// Ambient Music - Plays an mp3 music file to players.
//=========================================================
class CMAmbientMusic : public CMBaseMonster
{
public:
void Spawn(void);
//void Precache(void); // accessed before entvars are valid, manual precache in monster_config.cpp
void KeyValue(KeyValueData* pkvd);
void EXPORT MusicUse(edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value);
BOOL m_fPlaying; // music is active
};
//=========================================================
// XenMaker - spawns a monster with a teleportation effect.
//=========================================================
class CMXenMaker : public CMBaseMonster
{
public:
void Spawn(void);
void Precache(void);
void KeyValue(KeyValueData* pkvd);
void EXPORT CyclicUse(edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value);
void EXPORT RetryThink(void);
void StartEffect(void);
void EXPORT MiddleEffect(void);
void EXPORT EndEffect(void);
int m_iMonsterIndex;// index of the monster that will be created.
float m_flBeamRadius; // Maximum beam strike radius.
int m_iBeamAlpha;
int m_iBeamCount; // Number of single beam instances.
Vector m_vBeamColor;
float m_flLightRadius;
Vector m_vLightColor;
float m_flStartSpriteFramerate;
float m_flStartSpriteScale;
int m_iStartSpriteAlpha;
Vector m_vStartSpriteColor;
float m_flEndSpriteFramerate;
float m_flEndSpriteScale;
int m_iEndSpriteAlpha;
Vector m_vEndSpriteColor;
private:
void SpawnBeam(void);
int m_iBeamIndex;
};
//=========================================================
// Set CVar - Adjust a map CVar when triggered.
//=========================================================
class CMSetCVar : public CMBaseMonster
{
public:
void Spawn(void);
void KeyValue(KeyValueData* pkvd);
void EXPORT ActUse(edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value);
string_t m_iszCVarToChange;
};
#endif // BASEEXTRA_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,53 +1,81 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* This source code contains proprietary and confidential information of * This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to * Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access, * persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal. * use or distribution of this code by or to any unlicensed person is illegal.
* *
****/ ****/
// Base class for flying monsters. This overrides the movement test & execution code from CBaseMonster // Base class for flying monsters. This overrides the movement test & execution code from CBaseMonster
#ifndef FLYINGMONSTER_H #ifndef FLYINGMONSTER_H
#define FLYINGMONSTER_H #define FLYINGMONSTER_H
class CMFlyingMonster : public CMBaseMonster #include "cmbasemonster.h"
{
public: class CMFlyingMonster : public CMBaseMonster
int CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, edict_t *pTarget, float *pflDist );// check validity of a straight move through space {
BOOL FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, edict_t *pTargetEnt, Vector *pApex ); public:
Activity GetStoppedActivity( void ); int CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, edict_t *pTarget, float *pflDist );// check validity of a straight move through space
void Killed( entvars_t *pevAttacker, int iGib ); BOOL FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, edict_t *pTargetEnt, Vector *pApex );
void Stop( void ); Activity GetStoppedActivity( void );
float ChangeYaw( int speed ); void Killed( entvars_t *pevAttacker, int iGib );
void HandleAnimEvent( MonsterEvent_t *pEvent ); void Stop( void );
void MoveExecute( edict_t *pTargetEnt, const Vector &vecDir, float flInterval ); float ChangeYaw( int speed );
void Move( float flInterval = 0.1 ); void HandleAnimEvent( MonsterEvent_t *pEvent );
BOOL ShouldAdvanceRoute( float flWaypointDist ); void MoveExecute( edict_t *pTargetEnt, const Vector &vecDir, float flInterval );
void Move( float flInterval = 0.1 );
inline void SetFlyingMomentum( float momentum ) { m_momentum = momentum; } BOOL ShouldAdvanceRoute( float flWaypointDist );
inline void SetFlyingFlapSound( const char *pFlapSound ) { m_pFlapSound = pFlapSound; }
inline void SetFlyingSpeed( float speed ) { m_flightSpeed = speed; } inline void SetFlyingMomentum( float momentum ) { m_momentum = momentum; }
float CeilingZ( const Vector &position ); inline void SetFlyingFlapSound( const char *pFlapSound ) { m_pFlapSound = pFlapSound; }
float FloorZ( const Vector &position ); inline void SetFlyingSpeed( float speed ) { m_flightSpeed = speed; }
BOOL ProbeZ( const Vector &position, const Vector &probe, float *pFraction ); float CeilingZ( const Vector &position );
float FloorZ( const Vector &position );
BOOL ProbeZ( const Vector &position, const Vector &probe, float *pFraction );
// UNDONE: Save/restore this stuff!!!
protected:
Vector m_vecTravel; // Current direction // UNDONE: Save/restore this stuff!!!
float m_flightSpeed; // Current flight speed (decays when not flapping or gliding) protected:
float m_stopTime; // Last time we stopped (to avoid switching states too soon) Vector m_vecTravel; // Current direction
float m_momentum; // Weight for desired vs. momentum velocity float m_flightSpeed; // Current flight speed (decays when not flapping or gliding)
const char *m_pFlapSound; float m_stopTime; // Last time we stopped (to avoid switching states too soon)
}; float m_momentum; // Weight for desired vs. momentum velocity
const char *m_pFlapSound;
};
#endif //FLYINGMONSTER_H
//=========================================================
// Stukabat
//=========================================================
class CMStukabat : public CMFlyingMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int Classify ( void );
void SetActivity ( Activity NewActivity );
void HandleAnimEvent( MonsterEvent_t *pEvent );
Schedule_t *GetScheduleOfType ( int Type );
int GetBitePitch( void ) { return PITCH_NORM + RANDOM_LONG( 40, 50 ); }
BOOL CheckRangeAttack1 ( float flDot, float flDist );
// Not used
BOOL CheckRangeAttack2 ( float flDot, float flDist ) { return FALSE; }
BOOL CheckMeleeAttack1 ( float flDot, float flDist ) { return FALSE; }
BOOL CheckMeleeAttack2 ( float flDot, float flDist ) { return FALSE; }
CUSTOM_SCHEDULES
};
#endif //FLYINGMONSTER_H

View File

@@ -1,178 +1,178 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* This source code contains proprietary and confidential information of * This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to * Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access, * persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal. * use or distribution of this code by or to any unlicensed person is illegal.
* *
****/ ****/
#ifndef TALKMONSTER_H #ifndef TALKMONSTER_H
#define TALKMONSTER_H #define TALKMONSTER_H
#ifndef MONSTERS_H #ifndef MONSTERS_H
#include "monsters.h" #include "monsters.h"
#endif #endif
//========================================================= //=========================================================
// Talking monster base class // Talking monster base class
// Used for scientists and barneys // Used for scientists and barneys
//========================================================= //=========================================================
#define TALKRANGE_MIN 500.0 // don't talk to anyone farther away than this #define TALKRANGE_MIN 500.0 // don't talk to anyone farther away than this
#define TLK_STARE_DIST 128 // anyone closer than this and looking at me is probably staring at me. #define TLK_STARE_DIST 128 // anyone closer than this and looking at me is probably staring at me.
#define bit_saidDamageLight (1<<0) // bits so we don't repeat key sentences #define bit_saidDamageLight (1<<0) // bits so we don't repeat key sentences
#define bit_saidDamageMedium (1<<1) #define bit_saidDamageMedium (1<<1)
#define bit_saidDamageHeavy (1<<2) #define bit_saidDamageHeavy (1<<2)
#define bit_saidHelloPlayer (1<<3) #define bit_saidHelloPlayer (1<<3)
#define bit_saidWoundLight (1<<4) #define bit_saidWoundLight (1<<4)
#define bit_saidWoundHeavy (1<<5) #define bit_saidWoundHeavy (1<<5)
#define bit_saidHeard (1<<6) #define bit_saidHeard (1<<6)
#define bit_saidSmelled (1<<7) #define bit_saidSmelled (1<<7)
#define TLK_CFRIENDS 3 #define TLK_CFRIENDS 3
typedef enum typedef enum
{ {
TLK_ANSWER = 0, TLK_ANSWER = 0,
TLK_QUESTION, TLK_QUESTION,
TLK_IDLE, TLK_IDLE,
TLK_STARE, TLK_STARE,
TLK_USE, TLK_USE,
TLK_UNUSE, TLK_UNUSE,
TLK_STOP, TLK_STOP,
TLK_NOSHOOT, TLK_NOSHOOT,
TLK_HELLO, TLK_HELLO,
TLK_PHELLO, TLK_PHELLO,
TLK_PIDLE, TLK_PIDLE,
TLK_PQUESTION, TLK_PQUESTION,
TLK_PLHURT1, TLK_PLHURT1,
TLK_PLHURT2, TLK_PLHURT2,
TLK_PLHURT3, TLK_PLHURT3,
TLK_SMELL, TLK_SMELL,
TLK_WOUND, TLK_WOUND,
TLK_MORTAL, TLK_MORTAL,
TLK_CGROUPS, // MUST be last entry TLK_CGROUPS, // MUST be last entry
} TALKGROUPNAMES; } TALKGROUPNAMES;
enum enum
{ {
SCHED_CANT_FOLLOW = LAST_COMMON_SCHEDULE + 1, SCHED_CANT_FOLLOW = LAST_COMMON_SCHEDULE + 1,
SCHED_MOVE_AWAY, // Try to get out of the player's way SCHED_MOVE_AWAY, // Try to get out of the player's way
SCHED_MOVE_AWAY_FOLLOW, // same, but follow afterward SCHED_MOVE_AWAY_FOLLOW, // same, but follow afterward
SCHED_MOVE_AWAY_FAIL, // Turn back toward player SCHED_MOVE_AWAY_FAIL, // Turn back toward player
LAST_TALKMONSTER_SCHEDULE, // MUST be last LAST_TALKMONSTER_SCHEDULE, // MUST be last
}; };
enum enum
{ {
TASK_CANT_FOLLOW = LAST_COMMON_TASK + 1, TASK_CANT_FOLLOW = LAST_COMMON_TASK + 1,
TASK_MOVE_AWAY_PATH, TASK_MOVE_AWAY_PATH,
TASK_WALK_PATH_FOR_UNITS, TASK_WALK_PATH_FOR_UNITS,
TASK_TLK_RESPOND, // say my response TASK_TLK_RESPOND, // say my response
TASK_TLK_SPEAK, // question or remark TASK_TLK_SPEAK, // question or remark
TASK_TLK_HELLO, // Try to say hello to player TASK_TLK_HELLO, // Try to say hello to player
TASK_TLK_HEADRESET, // reset head position TASK_TLK_HEADRESET, // reset head position
TASK_TLK_STOPSHOOTING, // tell player to stop shooting friend TASK_TLK_STOPSHOOTING, // tell player to stop shooting friend
TASK_TLK_STARE, // let the player know I know he's staring at me. TASK_TLK_STARE, // let the player know I know he's staring at me.
TASK_TLK_LOOK_AT_CLIENT,// faces player if not moving and not talking and in idle. TASK_TLK_LOOK_AT_CLIENT,// faces player if not moving and not talking and in idle.
TASK_TLK_CLIENT_STARE, // same as look at client, but says something if the player stares. TASK_TLK_CLIENT_STARE, // same as look at client, but says something if the player stares.
TASK_TLK_EYECONTACT, // maintain eyecontact with person who I'm talking to TASK_TLK_EYECONTACT, // maintain eyecontact with person who I'm talking to
TASK_TLK_IDEALYAW, // set ideal yaw to face who I'm talking to TASK_TLK_IDEALYAW, // set ideal yaw to face who I'm talking to
TASK_FACE_PLAYER, // Face the player TASK_FACE_PLAYER, // Face the player
LAST_TALKMONSTER_TASK, // MUST be last LAST_TALKMONSTER_TASK, // MUST be last
}; };
class CMTalkMonster : public CMBaseMonster class CMTalkMonster : public CMBaseMonster
{ {
public: public:
void TalkInit( void ); void TalkInit( void );
edict_t *FindNearestFriend(BOOL fPlayer); edict_t *FindNearestFriend(BOOL fPlayer);
float TargetDistance( void ); float TargetDistance( void );
void StopTalking( void ) { SentenceStop(); } void StopTalking( void ) { SentenceStop(); }
// Base Monster functions // Base Monster functions
void Precache( void ); void Precache( void );
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType);
void TalkTouch( edict_t *pOther ); void TalkTouch( edict_t *pOther );
void Killed( entvars_t *pevAttacker, int iGib ); void Killed( entvars_t *pevAttacker, int iGib );
int IRelationship ( CMBaseEntity *pTarget ); int IRelationship ( CMBaseEntity *pTarget );
virtual int CanPlaySentence( BOOL fDisregardState ); virtual int CanPlaySentence( BOOL fDisregardState );
virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ); virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation );
void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, edict_t *pListener ); void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, edict_t *pListener );
void KeyValue( KeyValueData *pkvd ); void KeyValue( KeyValueData *pkvd );
// AI functions // AI functions
void SetActivity ( Activity newActivity ); void SetActivity ( Activity newActivity );
Schedule_t *GetScheduleOfType ( int Type ); Schedule_t *GetScheduleOfType ( int Type );
void StartTask( Task_t *pTask ); void StartTask( Task_t *pTask );
void RunTask( Task_t *pTask ); void RunTask( Task_t *pTask );
void HandleAnimEvent( MonsterEvent_t *pEvent ); void HandleAnimEvent( MonsterEvent_t *pEvent );
void PrescheduleThink( void ); void PrescheduleThink( void );
// Conversations / communication // Conversations / communication
int GetVoicePitch( void ); int GetVoicePitch( void );
void IdleRespond( void ); void IdleRespond( void );
int FIdleSpeak( void ); int FIdleSpeak( void );
int FIdleStare( void ); int FIdleStare( void );
int FIdleHello( void ); int FIdleHello( void );
void IdleHeadTurn( Vector &vecFriend ); void IdleHeadTurn( Vector &vecFriend );
int FOkToSpeak( void ); virtual int FOkToSpeak( void );
void TrySmellTalk( void ); void TrySmellTalk( void );
edict_t *EnumFriends( edict_t *pentPrevious, int listNumber, BOOL bTrace ); edict_t *EnumFriends( edict_t *pentPrevious, int listNumber, BOOL bTrace );
void AlertFriends( void ); void AlertFriends( void );
void ShutUpFriends( void ); void ShutUpFriends( void );
BOOL IsTalking( void ); BOOL IsTalking( void );
void Talk( float flDuration ); void Talk( float flDuration );
// For following // For following
BOOL CanFollow( void ); BOOL CanFollow( void );
BOOL IsFollowing( void ) { return m_hTargetEnt != NULL && UTIL_IsPlayer(m_hTargetEnt); } BOOL IsFollowing( void ) { return m_hTargetEnt != NULL && UTIL_IsPlayer(m_hTargetEnt); }
void StopFollowing( BOOL clearSchedule ); void StopFollowing( BOOL clearSchedule );
void StartFollowing( edict_t *pLeader ); void StartFollowing( edict_t *pLeader );
virtual void DeclineFollowing( void ) {} virtual void DeclineFollowing( void ) {}
void LimitFollowers( edict_t *pPlayer, int maxFollowers ); void LimitFollowers( edict_t *pPlayer, int maxFollowers );
void EXPORT FollowerUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value ); void EXPORT FollowerUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value );
virtual void SetAnswerQuestion( edict_t *pSpeaker ); virtual void SetAnswerQuestion( edict_t *pSpeaker );
virtual int FriendNumber( int arrayNumber ) { return arrayNumber; } virtual int FriendNumber( int arrayNumber ) { return arrayNumber; }
static char *m_szFriends[TLK_CFRIENDS]; // array of friend names static char *m_szFriends[TLK_CFRIENDS]; // array of friend names
static float g_talkWaitTime; static float g_talkWaitTime;
int m_bitsSaid; // set bits for sentences we don't want repeated int m_bitsSaid; // set bits for sentences we don't want repeated
int m_nSpeak; // number of times initiated talking int m_nSpeak; // number of times initiated talking
int m_voicePitch; // pitch of voice for this head int m_voicePitch; // pitch of voice for this head
const char *m_szGrp[TLK_CGROUPS]; // sentence group names const char *m_szGrp[TLK_CGROUPS]; // sentence group names
float m_useTime; // Don't allow +USE until this time float m_useTime; // Don't allow +USE until this time
int m_iszUse; // Custom +USE sentence group (follow) int m_iszUse; // Custom +USE sentence group (follow)
int m_iszUnUse; // Custom +USE sentence group (stop following) int m_iszUnUse; // Custom +USE sentence group (stop following)
float m_flLastSaidSmelled;// last time we talked about something that stinks float m_flLastSaidSmelled;// last time we talked about something that stinks
float m_flStopTalkTime;// when in the future that I'll be done saying this sentence. float m_flStopTalkTime;// when in the future that I'll be done saying this sentence.
EHANDLE m_hTalkTarget; // who to look at while talking EHANDLE m_hTalkTarget; // who to look at while talking
CUSTOM_SCHEDULES; CUSTOM_SCHEDULES;
}; };
// Clients can push talkmonsters out of their way // Clients can push talkmonsters out of their way
#define bits_COND_CLIENT_PUSH ( bits_COND_SPECIAL1 ) #define bits_COND_CLIENT_PUSH ( bits_COND_SPECIAL1 )
// Don't see a client right now. // Don't see a client right now.
#define bits_COND_CLIENT_UNSEEN ( bits_COND_SPECIAL2 ) #define bits_COND_CLIENT_UNSEEN ( bits_COND_SPECIAL2 )
#endif //TALKMONSTER_H #endif //TALKMONSTER_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,75 +1,75 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef DECALS_H #ifndef DECALS_H
#define DECALS_H #define DECALS_H
// //
// Dynamic Decals // Dynamic Decals
// //
enum decal_e enum decal_e
{ {
DECAL_GUNSHOT1 = 0, DECAL_GUNSHOT1 = 0,
DECAL_GUNSHOT2, DECAL_GUNSHOT2,
DECAL_GUNSHOT3, DECAL_GUNSHOT3,
DECAL_GUNSHOT4, DECAL_GUNSHOT4,
DECAL_GUNSHOT5, DECAL_GUNSHOT5,
DECAL_LAMBDA1, DECAL_LAMBDA1,
DECAL_LAMBDA2, DECAL_LAMBDA2,
DECAL_LAMBDA3, DECAL_LAMBDA3,
DECAL_LAMBDA4, DECAL_LAMBDA4,
DECAL_LAMBDA5, DECAL_LAMBDA5,
DECAL_LAMBDA6, DECAL_LAMBDA6,
DECAL_SCORCH1, DECAL_SCORCH1,
DECAL_SCORCH2, DECAL_SCORCH2,
DECAL_BLOOD1, DECAL_BLOOD1,
DECAL_BLOOD2, DECAL_BLOOD2,
DECAL_BLOOD3, DECAL_BLOOD3,
DECAL_BLOOD4, DECAL_BLOOD4,
DECAL_BLOOD5, DECAL_BLOOD5,
DECAL_BLOOD6, DECAL_BLOOD6,
DECAL_YBLOOD1, DECAL_YBLOOD1,
DECAL_YBLOOD2, DECAL_YBLOOD2,
DECAL_YBLOOD3, DECAL_YBLOOD3,
DECAL_YBLOOD4, DECAL_YBLOOD4,
DECAL_YBLOOD5, DECAL_YBLOOD5,
DECAL_YBLOOD6, DECAL_YBLOOD6,
DECAL_GLASSBREAK1, DECAL_GLASSBREAK1,
DECAL_GLASSBREAK2, DECAL_GLASSBREAK2,
DECAL_GLASSBREAK3, DECAL_GLASSBREAK3,
DECAL_BIGSHOT1, DECAL_BIGSHOT1,
DECAL_BIGSHOT2, DECAL_BIGSHOT2,
DECAL_BIGSHOT3, DECAL_BIGSHOT3,
DECAL_BIGSHOT4, DECAL_BIGSHOT4,
DECAL_BIGSHOT5, DECAL_BIGSHOT5,
DECAL_SPIT1, DECAL_SPIT1,
DECAL_SPIT2, DECAL_SPIT2,
DECAL_BPROOF1, // Bulletproof glass decal DECAL_BPROOF1, // Bulletproof glass decal
DECAL_GARGSTOMP1, // Gargantua stomp crack DECAL_GARGSTOMP1, // Gargantua stomp crack
DECAL_SMALLSCORCH1, // Small scorch mark DECAL_SMALLSCORCH1, // Small scorch mark
DECAL_SMALLSCORCH2, // Small scorch mark DECAL_SMALLSCORCH2, // Small scorch mark
DECAL_SMALLSCORCH3, // Small scorch mark DECAL_SMALLSCORCH3, // Small scorch mark
DECAL_MOMMABIRTH, // Big momma birth splatter DECAL_MOMMABIRTH, // Big momma birth splatter
DECAL_MOMMASPLAT, DECAL_MOMMASPLAT,
}; };
typedef struct typedef struct
{ {
char *name; char *name;
int index; int index;
} DLL_DECALLIST; } DLL_DECALLIST;
extern DLL_DECALLIST gDecals[]; extern DLL_DECALLIST gDecals[];
#endif // DECALS_H #endif // DECALS_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,98 +1,98 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* This source code contains proprietary and confidential information of * This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to * Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access, * persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal. * use or distribution of this code by or to any unlicensed person is illegal.
* *
****/ ****/
#ifndef DEFAULTAI_H #ifndef DEFAULTAI_H
#define DEFAULTAI_H #define DEFAULTAI_H
//========================================================= //=========================================================
// Failed // Failed
//========================================================= //=========================================================
extern Schedule_t slFail[]; extern Schedule_t slFail[];
//========================================================= //=========================================================
// Idle Schedules // Idle Schedules
//========================================================= //=========================================================
extern Schedule_t slIdleStand[]; extern Schedule_t slIdleStand[];
extern Schedule_t slIdleTrigger[]; extern Schedule_t slIdleTrigger[];
extern Schedule_t slIdleWalk[]; extern Schedule_t slIdleWalk[];
//========================================================= //=========================================================
// Wake Schedules // Wake Schedules
//========================================================= //=========================================================
extern Schedule_t slWakeAngry[]; extern Schedule_t slWakeAngry[];
//========================================================= //=========================================================
// AlertTurn Schedules // AlertTurn Schedules
//========================================================= //=========================================================
extern Schedule_t slAlertFace[]; extern Schedule_t slAlertFace[];
//========================================================= //=========================================================
// AlertIdle Schedules // AlertIdle Schedules
//========================================================= //=========================================================
extern Schedule_t slAlertStand[]; extern Schedule_t slAlertStand[];
//========================================================= //=========================================================
// CombatIdle Schedule // CombatIdle Schedule
//========================================================= //=========================================================
extern Schedule_t slCombatStand[]; extern Schedule_t slCombatStand[];
//========================================================= //=========================================================
// CombatFace Schedule // CombatFace Schedule
//========================================================= //=========================================================
extern Schedule_t slCombatFace[]; extern Schedule_t slCombatFace[];
//========================================================= //=========================================================
// reload schedule // reload schedule
//========================================================= //=========================================================
extern Schedule_t slReload[]; extern Schedule_t slReload[];
//========================================================= //=========================================================
// Attack Schedules // Attack Schedules
//========================================================= //=========================================================
extern Schedule_t slRangeAttack1[]; extern Schedule_t slRangeAttack1[];
extern Schedule_t slRangeAttack2[]; extern Schedule_t slRangeAttack2[];
extern Schedule_t slTakeCoverFromBestSound[]; extern Schedule_t slTakeCoverFromBestSound[];
// primary melee attack // primary melee attack
extern Schedule_t slMeleeAttack[]; extern Schedule_t slMeleeAttack[];
// Chase enemy schedule // Chase enemy schedule
extern Schedule_t slChaseEnemy[]; extern Schedule_t slChaseEnemy[];
//========================================================= //=========================================================
// small flinch, used when a relatively minor bit of damage // small flinch, used when a relatively minor bit of damage
// is inflicted. // is inflicted.
//========================================================= //=========================================================
extern Schedule_t slSmallFlinch[]; extern Schedule_t slSmallFlinch[];
//========================================================= //=========================================================
// Die! // Die!
//========================================================= //=========================================================
extern Schedule_t slDie[]; extern Schedule_t slDie[];
//========================================================= //=========================================================
// Universal Error Schedule // Universal Error Schedule
//========================================================= //=========================================================
extern Schedule_t slError[]; extern Schedule_t slError[];
//========================================================= //=========================================================
// Scripted sequences // Scripted sequences
//========================================================= //=========================================================
extern Schedule_t slWalkToScript[]; extern Schedule_t slWalkToScript[];
extern Schedule_t slRunToScript[]; extern Schedule_t slRunToScript[];
extern Schedule_t slWaitScript[]; extern Schedule_t slWaitScript[];
#endif // DEFAULTAI_H #endif // DEFAULTAI_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +1,33 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef DOORS_H #ifndef DOORS_H
#define DOORS_H #define DOORS_H
// doors // doors
#define SF_DOOR_ROTATE_Y 0 #define SF_DOOR_ROTATE_Y 0
#define SF_DOOR_START_OPEN 1 #define SF_DOOR_START_OPEN 1
#define SF_DOOR_ROTATE_BACKWARDS 2 #define SF_DOOR_ROTATE_BACKWARDS 2
#define SF_DOOR_PASSABLE 8 #define SF_DOOR_PASSABLE 8
#define SF_DOOR_ONEWAY 16 #define SF_DOOR_ONEWAY 16
#define SF_DOOR_NO_AUTO_RETURN 32 #define SF_DOOR_NO_AUTO_RETURN 32
#define SF_DOOR_ROTATE_Z 64 #define SF_DOOR_ROTATE_Z 64
#define SF_DOOR_ROTATE_X 128 #define SF_DOOR_ROTATE_X 128
#define SF_DOOR_USE_ONLY 256 // door must be opened by player's use button. #define SF_DOOR_USE_ONLY 256 // door must be opened by player's use button.
#define SF_DOOR_NOMONSTERS 512 // Monster can't open #define SF_DOOR_NOMONSTERS 512 // Monster can't open
#define SF_DOOR_SILENT 0x80000000 #define SF_DOOR_SILENT 0x80000000
#endif //DOORS_H #endif //DOORS_H

View File

@@ -1,446 +1,450 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#include "extdll.h" #include "extdll.h"
#include "util.h" #include "util.h"
#include "cmbase.h" #include "cmbase.h"
#include "cmbasemonster.h" #include "cmbasemonster.h"
#include "monsters.h" #include "monsters.h"
#include "customentity.h" #include "customentity.h"
#include "effects.h" #include "effects.h"
#include "weapons.h" #include "weapons.h"
#include "decals.h" #include "decals.h"
#include "func_break.h" #include "func_break.h"
#include "shake.h" #include "shake.h"
#define SF_GIBSHOOTER_REPEATABLE 1 // allows a gibshooter to be refired #define SF_GIBSHOOTER_REPEATABLE 1 // allows a gibshooter to be refired
#define SF_FUNNEL_REVERSE 1 // funnel effect repels particles instead of attracting them. #define SF_FUNNEL_REVERSE 1 // funnel effect repels particles instead of attracting them.
// -------------------------------------------------- // --------------------------------------------------
// //
// Beams // Beams
// //
// -------------------------------------------------- // --------------------------------------------------
void CMBeam::Spawn( void ) void CMBeam::Spawn( void )
{ {
pev->solid = SOLID_NOT; // Remove model & collisions pev->solid = SOLID_NOT; // Remove model & collisions
Precache( ); Precache( );
} }
void CMBeam::Precache( void ) void CMBeam::Precache( void )
{ {
if ( pev->owner ) if ( pev->owner )
SetStartEntity( ENTINDEX( pev->owner ) ); SetStartEntity( ENTINDEX( pev->owner ) );
if ( pev->aiment ) if ( pev->aiment )
SetEndEntity( ENTINDEX( pev->aiment ) ); SetEndEntity( ENTINDEX( pev->aiment ) );
} }
void CMBeam::SetStartEntity( int entityIndex ) void CMBeam::SetStartEntity( int entityIndex )
{ {
pev->sequence = (entityIndex & 0x0FFF) | ((pev->sequence&0xF000)<<12); pev->sequence = (entityIndex & 0x0FFF) | ((pev->sequence&0xF000)<<12);
pev->owner = g_engfuncs.pfnPEntityOfEntIndex( entityIndex ); pev->owner = g_engfuncs.pfnPEntityOfEntIndex( entityIndex );
} }
void CMBeam::SetEndEntity( int entityIndex ) void CMBeam::SetEndEntity( int entityIndex )
{ {
pev->skin = (entityIndex & 0x0FFF) | ((pev->skin&0xF000)<<12); pev->skin = (entityIndex & 0x0FFF) | ((pev->skin&0xF000)<<12);
pev->aiment = g_engfuncs.pfnPEntityOfEntIndex( entityIndex ); pev->aiment = g_engfuncs.pfnPEntityOfEntIndex( entityIndex );
} }
// These don't take attachments into account // These don't take attachments into account
const Vector &CMBeam::GetStartPos( void ) const Vector &CMBeam::GetStartPos( void )
{ {
if ( GetType() == BEAM_ENTS ) if ( GetType() == BEAM_ENTS )
{ {
edict_t *pent = g_engfuncs.pfnPEntityOfEntIndex( GetStartEntity() ); edict_t *pent = g_engfuncs.pfnPEntityOfEntIndex( GetStartEntity() );
return pent->v.origin; return pent->v.origin;
} }
return pev->origin; return pev->origin;
} }
const Vector &CMBeam::GetEndPos( void ) const Vector &CMBeam::GetEndPos( void )
{ {
int type = GetType(); int type = GetType();
if ( type == BEAM_POINTS || type == BEAM_HOSE ) if ( type == BEAM_POINTS || type == BEAM_HOSE )
{ {
return pev->angles; return pev->angles;
} }
edict_t *pent = g_engfuncs.pfnPEntityOfEntIndex( GetEndEntity() ); edict_t *pent = g_engfuncs.pfnPEntityOfEntIndex( GetEndEntity() );
if ( pent ) if ( pent )
return pent->v.origin; return pent->v.origin;
return pev->angles; return pev->angles;
} }
CMBeam *CMBeam::BeamCreate( const char *pSpriteName, int width ) CMBeam *CMBeam::BeamCreate( const char *pSpriteName, int width )
{ {
// Create a new entity with CMBeam private data // Create a new entity with CMBeam private data
CMBeam *pBeam = CreateClassPtr( (CMBeam *)NULL ); CMBeam *pBeam = CreateClassPtr( (CMBeam *)NULL );
if (pBeam == NULL) if (pBeam == NULL)
return NULL; return NULL;
pBeam->pev->classname = MAKE_STRING("beam"); pBeam->pev->classname = MAKE_STRING("beam");
pBeam->BeamInit( pSpriteName, width ); pBeam->BeamInit( pSpriteName, width );
return pBeam; return pBeam;
} }
void CMBeam::BeamInit( const char *pSpriteName, int width ) void CMBeam::BeamInit( const char *pSpriteName, int width )
{ {
pev->flags |= FL_CUSTOMENTITY; pev->flags |= FL_CUSTOMENTITY;
SetColor( 255, 255, 255 ); SetColor( 255, 255, 255 );
SetBrightness( 255 ); SetBrightness( 255 );
SetNoise( 0 ); SetNoise( 0 );
SetFrame( 0 ); SetFrame( 0 );
SetScrollRate( 0 ); SetScrollRate( 0 );
pev->model = MAKE_STRING( pSpriteName ); pev->model = MAKE_STRING( pSpriteName );
SetTexture( PRECACHE_MODEL( (char *)pSpriteName ) ); SetTexture( PRECACHE_MODELINDEX( (char *)pSpriteName ) );
SetWidth( width ); SetWidth( width );
pev->skin = 0; pev->skin = 0;
pev->sequence = 0; pev->sequence = 0;
pev->rendermode = 0; pev->rendermode = 0;
} }
void CMBeam::PointsInit( const Vector &start, const Vector &end ) void CMBeam::PointsInit( const Vector &start, const Vector &end )
{ {
SetType( BEAM_POINTS ); SetType( BEAM_POINTS );
SetStartPos( start ); SetStartPos( start );
SetEndPos( end ); SetEndPos( end );
SetStartAttachment( 0 ); SetStartAttachment( 0 );
SetEndAttachment( 0 ); SetEndAttachment( 0 );
RelinkBeam(); RelinkBeam();
} }
void CMBeam::HoseInit( const Vector &start, const Vector &direction ) void CMBeam::HoseInit( const Vector &start, const Vector &direction )
{ {
SetType( BEAM_HOSE ); SetType( BEAM_HOSE );
SetStartPos( start ); SetStartPos( start );
SetEndPos( direction ); SetEndPos( direction );
SetStartAttachment( 0 ); SetStartAttachment( 0 );
SetEndAttachment( 0 ); SetEndAttachment( 0 );
RelinkBeam(); RelinkBeam();
} }
void CMBeam::PointEntInit( const Vector &start, int endIndex ) void CMBeam::PointEntInit( const Vector &start, int endIndex )
{ {
SetType( BEAM_ENTPOINT ); SetType( BEAM_ENTPOINT );
SetStartPos( start ); SetStartPos( start );
SetEndEntity( endIndex ); SetEndEntity( endIndex );
SetStartAttachment( 0 ); SetStartAttachment( 0 );
SetEndAttachment( 0 ); SetEndAttachment( 0 );
RelinkBeam(); RelinkBeam();
} }
void CMBeam::EntsInit( int startIndex, int endIndex ) void CMBeam::EntsInit( int startIndex, int endIndex )
{ {
SetType( BEAM_ENTS ); SetType( BEAM_ENTS );
SetStartEntity( startIndex ); SetStartEntity( startIndex );
SetEndEntity( endIndex ); SetEndEntity( endIndex );
SetStartAttachment( 0 ); SetStartAttachment( 0 );
SetEndAttachment( 0 ); SetEndAttachment( 0 );
RelinkBeam(); RelinkBeam();
} }
void CMBeam::RelinkBeam( void ) void CMBeam::RelinkBeam( void )
{ {
const Vector &startPos = GetStartPos(), &endPos = GetEndPos(); const Vector &startPos = GetStartPos(), &endPos = GetEndPos();
pev->mins.x = min( startPos.x, endPos.x ); pev->mins.x = min( startPos.x, endPos.x );
pev->mins.y = min( startPos.y, endPos.y ); pev->mins.y = min( startPos.y, endPos.y );
pev->mins.z = min( startPos.z, endPos.z ); pev->mins.z = min( startPos.z, endPos.z );
pev->maxs.x = max( startPos.x, endPos.x ); pev->maxs.x = max( startPos.x, endPos.x );
pev->maxs.y = max( startPos.y, endPos.y ); pev->maxs.y = max( startPos.y, endPos.y );
pev->maxs.z = max( startPos.z, endPos.z ); pev->maxs.z = max( startPos.z, endPos.z );
pev->mins = pev->mins - pev->origin; pev->mins = pev->mins - pev->origin;
pev->maxs = pev->maxs - pev->origin; pev->maxs = pev->maxs - pev->origin;
UTIL_SetSize( pev, pev->mins, pev->maxs ); UTIL_SetSize( pev, pev->mins, pev->maxs );
UTIL_SetOrigin( pev, pev->origin ); UTIL_SetOrigin( pev, pev->origin );
} }
#if 0 #if 0
void CMBeam::SetObjectCollisionBox( void ) void CMBeam::SetObjectCollisionBox( void )
{ {
const Vector &startPos = GetStartPos(), &endPos = GetEndPos(); const Vector &startPos = GetStartPos(), &endPos = GetEndPos();
pev->absmin.x = min( startPos.x, endPos.x ); pev->absmin.x = min( startPos.x, endPos.x );
pev->absmin.y = min( startPos.y, endPos.y ); pev->absmin.y = min( startPos.y, endPos.y );
pev->absmin.z = min( startPos.z, endPos.z ); pev->absmin.z = min( startPos.z, endPos.z );
pev->absmax.x = max( startPos.x, endPos.x ); pev->absmax.x = max( startPos.x, endPos.x );
pev->absmax.y = max( startPos.y, endPos.y ); pev->absmax.y = max( startPos.y, endPos.y );
pev->absmax.z = max( startPos.z, endPos.z ); pev->absmax.z = max( startPos.z, endPos.z );
} }
#endif #endif
void CMBeam::TriggerTouch( edict_t *pOther ) void CMBeam::TriggerTouch( edict_t *pOther )
{ {
if ( pOther->v.flags & (FL_CLIENT | FL_MONSTER) ) if ( pOther->v.flags & (FL_CLIENT | FL_MONSTER) )
{ {
if ( pev->owner ) if ( pev->owner )
{ {
if (pev->owner->v.euser4 != NULL) if (pev->owner->v.euser4 != NULL)
{ {
CMBaseEntity *pOwner = GetClassPtr((CMBaseEntity *)VARS(pev->owner)); CMBaseEntity *pOwner = GetClassPtr((CMBaseEntity *)VARS(pev->owner));
pOwner->Use( pOther, this->edict(), USE_TOGGLE, 0 ); pOwner->Use( pOther, this->edict(), USE_TOGGLE, 0 );
} }
} }
ALERT( at_console, "Firing targets!!!\n" ); ALERT( at_console, "Firing targets!!!\n" );
} }
} }
edict_t *CMBeam::RandomTargetname( const char *szName ) edict_t *CMBeam::RandomTargetname( const char *szName )
{ {
int total = 0; int total = 0;
edict_t *pEntity = NULL; edict_t *pEntity = NULL;
edict_t *pNewEntity = NULL; edict_t *pNewEntity = NULL;
while ((pNewEntity = UTIL_FindEntityByTargetname( pNewEntity, szName )) != NULL) while ((pNewEntity = UTIL_FindEntityByTargetname( pNewEntity, szName )) != NULL)
{ {
total++; total++;
if (RANDOM_LONG(0,total-1) < 1) if (RANDOM_LONG(0,total-1) < 1)
pEntity = pNewEntity; pEntity = pNewEntity;
} }
return pEntity; return pEntity;
} }
void CMBeam::DoSparks( const Vector &start, const Vector &end ) void CMBeam::DoSparks( const Vector &start, const Vector &end )
{ {
if ( pev->spawnflags & (SF_BEAM_SPARKSTART|SF_BEAM_SPARKEND) ) if ( pev->spawnflags & (SF_BEAM_SPARKSTART|SF_BEAM_SPARKEND) )
{ {
if ( pev->spawnflags & SF_BEAM_SPARKSTART ) if ( pev->spawnflags & SF_BEAM_SPARKSTART )
{ {
UTIL_Sparks( start ); UTIL_Sparks( start );
} }
if ( pev->spawnflags & SF_BEAM_SPARKEND ) if ( pev->spawnflags & SF_BEAM_SPARKEND )
{ {
UTIL_Sparks( end ); UTIL_Sparks( end );
} }
} }
} }
void CMBeam::BeamDamage( TraceResult *ptr ) void CMBeam::BeamDamage( TraceResult *ptr )
{ {
RelinkBeam(); RelinkBeam();
if ( ptr->flFraction != 1.0 && ptr->pHit != NULL ) if ( ptr->flFraction != 1.0 && ptr->pHit != NULL )
{ {
if (UTIL_IsPlayer(ptr->pHit)) if (UTIL_IsPlayer(ptr->pHit))
{ {
ClearMultiDamage(); ClearMultiDamage();
UTIL_TraceAttack(ptr->pHit, pev, pev->dmg * (gpGlobals->time - pev->dmgtime), (ptr->vecEndPos - pev->origin).Normalize(), ptr, DMG_ENERGYBEAM ); UTIL_TraceAttack(ptr->pHit, pev, pev->dmg * (gpGlobals->time - pev->dmgtime), (ptr->vecEndPos - pev->origin).Normalize(), ptr, DMG_ENERGYBEAM );
ApplyMultiDamage( pev, pev ); ApplyMultiDamage( pev, pev );
if ( pev->spawnflags & SF_BEAM_DECALS ) if ( pev->spawnflags & SF_BEAM_DECALS )
{ {
if ( UTIL_IsBSPModel(ptr->pHit) ) if ( UTIL_IsBSPModel(ptr->pHit) )
UTIL_DecalTrace( ptr, DECAL_BIGSHOT1 + RANDOM_LONG(0,4) ); UTIL_DecalTrace( ptr, DECAL_BIGSHOT1 + RANDOM_LONG(0,4) );
} }
} }
else if (ptr->pHit->v.euser4 != NULL) else if (ptr->pHit->v.euser4 != NULL)
{ {
ClearMultiDamage(); ClearMultiDamage();
CMBaseEntity *pMonster = GetClassPtr((CMBaseEntity *)VARS(ptr->pHit)); CMBaseEntity *pMonster = GetClassPtr((CMBaseEntity *)VARS(ptr->pHit));
pMonster->TraceAttack( pev, pev->dmg * (gpGlobals->time - pev->dmgtime), (ptr->vecEndPos - pev->origin).Normalize(), ptr, DMG_ENERGYBEAM ); pMonster->TraceAttack( pev, pev->dmg * (gpGlobals->time - pev->dmgtime), (ptr->vecEndPos - pev->origin).Normalize(), ptr, DMG_ENERGYBEAM );
ApplyMultiDamage( pev, pev ); ApplyMultiDamage( pev, pev );
if ( pev->spawnflags & SF_BEAM_DECALS ) if ( pev->spawnflags & SF_BEAM_DECALS )
{ {
if ( pMonster->IsBSPModel() ) if ( pMonster->IsBSPModel() )
UTIL_DecalTrace( ptr, DECAL_BIGSHOT1 + RANDOM_LONG(0,4) ); UTIL_DecalTrace( ptr, DECAL_BIGSHOT1 + RANDOM_LONG(0,4) );
} }
} }
} }
pev->dmgtime = gpGlobals->time; pev->dmgtime = gpGlobals->time;
} }
void CMSprite::Spawn( void ) void CMSprite::Spawn( void )
{ {
pev->solid = SOLID_NOT; pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NONE; pev->movetype = MOVETYPE_NONE;
pev->effects = 0; pev->effects = 0;
pev->frame = 0; pev->frame = 0;
Precache(); Precache();
SET_MODEL( ENT(pev), STRING(pev->model) ); SET_MODEL( ENT(pev), STRING(pev->model) );
m_maxFrame = (float) MODEL_FRAMES( pev->modelindex ) - 1; m_maxFrame = (float) MODEL_FRAMES( pev->modelindex ) - 1;
if ( pev->targetname && !(pev->spawnflags & SF_SPRITE_STARTON) ) if ( pev->targetname && !(pev->spawnflags & SF_SPRITE_STARTON) )
TurnOff(); TurnOff();
else else
TurnOn(); TurnOn();
// Worldcraft only sets y rotation, copy to Z // Worldcraft only sets y rotation, copy to Z
if ( pev->angles.y != 0 && pev->angles.z == 0 ) if ( pev->angles.y != 0 && pev->angles.z == 0 )
{ {
pev->angles.z = pev->angles.y; pev->angles.z = pev->angles.y;
pev->angles.y = 0; pev->angles.y = 0;
} }
} }
void CMSprite::Precache( void ) void CMSprite::Precache( void )
{ {
PRECACHE_MODEL( (char *)STRING(pev->model) ); PRECACHE_MODEL( (char *)STRING(pev->model) );
// Reset attachment after save/restore // Reset attachment after save/restore
if ( pev->aiment ) if ( pev->aiment )
SetAttachment( pev->aiment, pev->body ); SetAttachment( pev->aiment, pev->body );
else else
{ {
// Clear attachment // Clear attachment
pev->skin = 0; pev->skin = 0;
pev->body = 0; pev->body = 0;
} }
} }
void CMSprite::SpriteInit( const char *pSpriteName, const Vector &origin ) void CMSprite::SpriteInit( const char *pSpriteName, const Vector &origin )
{ {
pev->model = MAKE_STRING(pSpriteName); pev->model = MAKE_STRING(pSpriteName);
pev->origin = origin; pev->origin = origin;
Spawn(); Spawn();
} }
CMSprite *CMSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate ) CMSprite *CMSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate )
{ {
CMSprite *pSprite = CreateClassPtr( (CMSprite *)NULL ); CMSprite *pSprite = CreateClassPtr( (CMSprite *)NULL );
pSprite->SpriteInit( pSpriteName, origin ); if (pSprite)
pSprite->pev->classname = MAKE_STRING("env_sprite"); {
pSprite->pev->solid = SOLID_NOT; pSprite->SpriteInit(pSpriteName, origin);
pSprite->pev->movetype = MOVETYPE_NOCLIP; pSprite->pev->classname = MAKE_STRING("env_sprite");
if ( animate ) pSprite->pev->solid = SOLID_NOT;
pSprite->TurnOn(); pSprite->pev->movetype = MOVETYPE_NOCLIP;
if (animate)
return pSprite; pSprite->TurnOn();
}
return pSprite;
}
void CMSprite::AnimateThink( void ) return NULL;
{ }
Animate( pev->framerate * (gpGlobals->time - m_lastTime) );
pev->nextthink = gpGlobals->time + 0.1; void CMSprite::AnimateThink( void )
m_lastTime = gpGlobals->time; {
} Animate( pev->framerate * (gpGlobals->time - m_lastTime) );
void CMSprite::AnimateUntilDead( void ) pev->nextthink = gpGlobals->time + 0.1;
{ m_lastTime = gpGlobals->time;
if ( gpGlobals->time > pev->dmgtime ) }
UTIL_Remove(this->edict());
else void CMSprite::AnimateUntilDead( void )
{ {
AnimateThink(); if ( gpGlobals->time > pev->dmgtime )
pev->nextthink = gpGlobals->time; UTIL_Remove(this->edict());
} else
} {
AnimateThink();
void CMSprite::Expand( float scaleSpeed, float fadeSpeed ) pev->nextthink = gpGlobals->time;
{ }
pev->speed = scaleSpeed; }
pev->health = fadeSpeed;
SetThink( &CMSprite::ExpandThink ); void CMSprite::Expand( float scaleSpeed, float fadeSpeed )
{
pev->nextthink = gpGlobals->time; pev->speed = scaleSpeed;
m_lastTime = gpGlobals->time; pev->health = fadeSpeed;
} SetThink( &CMSprite::ExpandThink );
pev->nextthink = gpGlobals->time;
void CMSprite::ExpandThink( void ) m_lastTime = gpGlobals->time;
{ }
float frametime = gpGlobals->time - m_lastTime;
pev->scale += pev->speed * frametime;
pev->renderamt -= pev->health * frametime; void CMSprite::ExpandThink( void )
if ( pev->renderamt <= 0 ) {
{ float frametime = gpGlobals->time - m_lastTime;
pev->renderamt = 0; pev->scale += pev->speed * frametime;
UTIL_Remove( this->edict() ); pev->renderamt -= pev->health * frametime;
} if ( pev->renderamt <= 0 )
else {
{ pev->renderamt = 0;
pev->nextthink = gpGlobals->time + 0.1; UTIL_Remove( this->edict() );
m_lastTime = gpGlobals->time; }
} else
} {
pev->nextthink = gpGlobals->time + 0.1;
m_lastTime = gpGlobals->time;
void CMSprite::Animate( float frames ) }
{ }
pev->frame += frames;
if ( pev->frame > m_maxFrame )
{ void CMSprite::Animate( float frames )
if ( pev->spawnflags & SF_SPRITE_ONCE ) {
{ pev->frame += frames;
TurnOff(); if ( pev->frame > m_maxFrame )
} {
else if ( pev->spawnflags & SF_SPRITE_ONCE )
{ {
if ( m_maxFrame > 0 ) TurnOff();
pev->frame = fmod( pev->frame, m_maxFrame ); }
} else
} {
} if ( m_maxFrame > 0 )
pev->frame = fmod( pev->frame, m_maxFrame );
}
void CMSprite::TurnOff( void ) }
{ }
pev->effects = EF_NODRAW;
pev->nextthink = 0;
} void CMSprite::TurnOff( void )
{
pev->effects = EF_NODRAW;
void CMSprite::TurnOn( void ) pev->nextthink = 0;
{ }
pev->effects = 0;
if ( (pev->framerate && m_maxFrame > 1.0) || (pev->spawnflags & SF_SPRITE_ONCE) )
{ void CMSprite::TurnOn( void )
SetThink( &CMSprite::AnimateThink ); {
pev->nextthink = gpGlobals->time; pev->effects = 0;
m_lastTime = gpGlobals->time; if ( (pev->framerate && m_maxFrame > 1.0) || (pev->spawnflags & SF_SPRITE_ONCE) )
} {
pev->frame = 0; SetThink( &CMSprite::AnimateThink );
} pev->nextthink = gpGlobals->time;
m_lastTime = gpGlobals->time;
}
void CMSprite::Use( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value ) pev->frame = 0;
{ }
int on = pev->effects != EF_NODRAW;
if ( ShouldToggle( useType, on ) )
{ void CMSprite::Use( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
if ( on ) {
{ int on = pev->effects != EF_NODRAW;
TurnOff(); if ( ShouldToggle( useType, on ) )
} {
else if ( on )
{ {
TurnOn(); TurnOff();
} }
} else
} {
TurnOn();
}
}
}

View File

@@ -1,203 +1,206 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef EFFECTS_H #ifndef EFFECTS_H
#define EFFECTS_H #define EFFECTS_H
#define SF_BEAM_STARTON 0x0001 #define SF_BEAM_STARTON 0x0001
#define SF_BEAM_TOGGLE 0x0002 #define SF_BEAM_TOGGLE 0x0002
#define SF_BEAM_RANDOM 0x0004 #define SF_BEAM_RANDOM 0x0004
#define SF_BEAM_RING 0x0008 #define SF_BEAM_RING 0x0008
#define SF_BEAM_SPARKSTART 0x0010 #define SF_BEAM_SPARKSTART 0x0010
#define SF_BEAM_SPARKEND 0x0020 #define SF_BEAM_SPARKEND 0x0020
#define SF_BEAM_DECALS 0x0040 #define SF_BEAM_DECALS 0x0040
#define SF_BEAM_SHADEIN 0x0080 #define SF_BEAM_SHADEIN 0x0080
#define SF_BEAM_SHADEOUT 0x0100 #define SF_BEAM_SHADEOUT 0x0100
#define SF_BEAM_TEMPORARY 0x8000 #define SF_BEAM_TEMPORARY 0x8000
#define SF_SPRITE_STARTON 0x0001 #define SF_SPRITE_STARTON 0x0001
#define SF_SPRITE_ONCE 0x0002 #define SF_SPRITE_ONCE 0x0002
#define SF_SPRITE_TEMPORARY 0x8000 #define SF_SPRITE_TEMPORARY 0x8000
class CMSprite : public CMPointEntity class CMSprite : public CMPointEntity
{ {
public: public:
void Spawn( void ); void Spawn( void );
void Precache( void ); void Precache( void );
int ObjectCaps( void ) int ObjectCaps( void )
{ {
int flags = 0; int flags = 0;
if ( pev->spawnflags & SF_SPRITE_TEMPORARY ) if ( pev->spawnflags & SF_SPRITE_TEMPORARY )
flags = FCAP_DONT_SAVE; flags = FCAP_DONT_SAVE;
return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags; return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags;
} }
void EXPORT AnimateThink( void ); void EXPORT AnimateThink( void );
void EXPORT ExpandThink( void ); void EXPORT ExpandThink( void );
void Use( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value ); void Use( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value );
void Animate( float frames ); void Animate( float frames );
void Expand( float scaleSpeed, float fadeSpeed ); void Expand( float scaleSpeed, float fadeSpeed );
void SpriteInit( const char *pSpriteName, const Vector &origin ); void SpriteInit( const char *pSpriteName, const Vector &origin );
inline void SetAttachment( edict_t *pEntity, int attachment ) inline void SetAttachment( edict_t *pEntity, int attachment )
{ {
if ( pEntity ) if ( pEntity )
{ {
pev->skin = ENTINDEX(pEntity); pev->skin = ENTINDEX(pEntity);
pev->body = attachment; pev->body = attachment;
pev->aiment = pEntity; pev->aiment = pEntity;
pev->movetype = MOVETYPE_FOLLOW; pev->movetype = MOVETYPE_FOLLOW;
} }
} }
void TurnOff( void ); void TurnOff( void );
void TurnOn( void ); void TurnOn( void );
inline float Frames( void ) { return m_maxFrame; } inline float Frames( void ) { return m_maxFrame; }
inline void SetTransparency( int rendermode, int r, int g, int b, int a, int fx ) inline void SetTransparency( int rendermode, int r, int g, int b, int a, int fx )
{ {
pev->rendermode = rendermode; pev->rendermode = rendermode;
pev->rendercolor.x = r; pev->rendercolor.x = r;
pev->rendercolor.y = g; pev->rendercolor.y = g;
pev->rendercolor.z = b; pev->rendercolor.z = b;
pev->renderamt = a; pev->renderamt = a;
pev->renderfx = fx; pev->renderfx = fx;
} }
inline void SetTexture( int spriteIndex ) { pev->modelindex = spriteIndex; } inline void SetTexture( int spriteIndex ) { pev->modelindex = spriteIndex; }
inline void SetScale( float scale ) { pev->scale = scale; } inline void SetScale( float scale ) { pev->scale = scale; }
inline void SetColor( int r, int g, int b ) { pev->rendercolor.x = r; pev->rendercolor.y = g; pev->rendercolor.z = b; } inline void SetColor( int r, int g, int b ) { pev->rendercolor.x = r; pev->rendercolor.y = g; pev->rendercolor.z = b; }
inline void SetBrightness( int brightness ) { pev->renderamt = brightness; } inline void SetBrightness( int brightness ) { pev->renderamt = brightness; }
inline void AnimateAndDie( float framerate ) inline void AnimateAndDie( float framerate )
{ {
SetThink(&CMSprite::AnimateUntilDead); pev->effects = 0;
pev->framerate = framerate; SetThink(&CMSprite::AnimateUntilDead);
pev->dmgtime = gpGlobals->time + (m_maxFrame / framerate); pev->framerate = framerate;
pev->nextthink = gpGlobals->time; pev->dmgtime = gpGlobals->time + (m_maxFrame / framerate);
} pev->nextthink = gpGlobals->time;
m_lastTime = gpGlobals->time;
void EXPORT AnimateUntilDead( void ); pev->frame = 0;
}
static CMSprite *SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate );
void EXPORT AnimateUntilDead( void );
private:
static CMSprite *SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate );
float m_lastTime;
float m_maxFrame; private:
};
float m_lastTime;
float m_maxFrame;
class CMBeam : public CMBaseEntity };
{
public:
void Spawn( void ); class CMBeam : public CMBaseEntity
void Precache( void ); {
int ObjectCaps( void ) public:
{ void Spawn( void );
int flags = 0; void Precache( void );
if ( pev->spawnflags & SF_BEAM_TEMPORARY ) int ObjectCaps( void )
flags = FCAP_DONT_SAVE; {
return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags; int flags = 0;
} if ( pev->spawnflags & SF_BEAM_TEMPORARY )
flags = FCAP_DONT_SAVE;
void EXPORT TriggerTouch( edict_t *pOther ); return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags;
}
// These functions are here to show the way beams are encoded as entities.
// Encoding beams as entities simplifies their management in the client/server architecture void EXPORT TriggerTouch( edict_t *pOther );
inline void SetType( int type ) { pev->rendermode = (pev->rendermode & 0xF0) | (type&0x0F); }
inline void SetFlags( int flags ) { pev->rendermode = (pev->rendermode & 0x0F) | (flags&0xF0); } // These functions are here to show the way beams are encoded as entities.
inline void SetStartPos( const Vector& pos ) { pev->origin = pos; } // Encoding beams as entities simplifies their management in the client/server architecture
inline void SetEndPos( const Vector& pos ) { pev->angles = pos; } inline void SetType( int type ) { pev->rendermode = (pev->rendermode & 0xF0) | (type&0x0F); }
void SetStartEntity( int entityIndex ); inline void SetFlags( int flags ) { pev->rendermode = (pev->rendermode & 0x0F) | (flags&0xF0); }
void SetEndEntity( int entityIndex ); inline void SetStartPos( const Vector& pos ) { pev->origin = pos; }
inline void SetEndPos( const Vector& pos ) { pev->angles = pos; }
inline void SetStartAttachment( int attachment ) { pev->sequence = (pev->sequence & 0x0FFF) | ((attachment&0xF)<<12); } void SetStartEntity( int entityIndex );
inline void SetEndAttachment( int attachment ) { pev->skin = (pev->skin & 0x0FFF) | ((attachment&0xF)<<12); } void SetEndEntity( int entityIndex );
inline void SetTexture( int spriteIndex ) { pev->modelindex = spriteIndex; } inline void SetStartAttachment( int attachment ) { pev->sequence = (pev->sequence & 0x0FFF) | ((attachment&0xF)<<12); }
inline void SetWidth( int width ) { pev->scale = width; } inline void SetEndAttachment( int attachment ) { pev->skin = (pev->skin & 0x0FFF) | ((attachment&0xF)<<12); }
inline void SetNoise( int amplitude ) { pev->body = amplitude; }
inline void SetColor( int r, int g, int b ) { pev->rendercolor.x = r; pev->rendercolor.y = g; pev->rendercolor.z = b; } inline void SetTexture( int spriteIndex ) { pev->modelindex = spriteIndex; }
inline void SetBrightness( int brightness ) { pev->renderamt = brightness; } inline void SetWidth( int width ) { pev->scale = width; }
inline void SetFrame( float frame ) { pev->frame = frame; } inline void SetNoise( int amplitude ) { pev->body = amplitude; }
inline void SetScrollRate( int speed ) { pev->animtime = speed; } inline void SetColor( int r, int g, int b ) { pev->rendercolor.x = r; pev->rendercolor.y = g; pev->rendercolor.z = b; }
inline void SetBrightness( int brightness ) { pev->renderamt = brightness; }
inline int GetType( void ) { return pev->rendermode & 0x0F; } inline void SetFrame( float frame ) { pev->frame = frame; }
inline int GetFlags( void ) { return pev->rendermode & 0xF0; } inline void SetScrollRate( int speed ) { pev->animtime = speed; }
inline int GetStartEntity( void ) { return pev->sequence & 0xFFF; }
inline int GetEndEntity( void ) { return pev->skin & 0xFFF; } inline int GetType( void ) { return pev->rendermode & 0x0F; }
inline int GetFlags( void ) { return pev->rendermode & 0xF0; }
const Vector &GetStartPos( void ); inline int GetStartEntity( void ) { return pev->sequence & 0xFFF; }
const Vector &GetEndPos( void ); inline int GetEndEntity( void ) { return pev->skin & 0xFFF; }
Vector Center( void ) { return (GetStartPos() + GetEndPos()) * 0.5; }; // center point of beam const Vector &GetStartPos( void );
const Vector &GetEndPos( void );
inline int GetTexture( void ) { return pev->modelindex; }
inline int GetWidth( void ) { return pev->scale; } Vector Center( void ) { return (GetStartPos() + GetEndPos()) * 0.5; }; // center point of beam
inline int GetNoise( void ) { return pev->body; }
// inline void GetColor( int r, int g, int b ) { pev->rendercolor.x = r; pev->rendercolor.y = g; pev->rendercolor.z = b; } inline int GetTexture( void ) { return pev->modelindex; }
inline int GetBrightness( void ) { return pev->renderamt; } inline int GetWidth( void ) { return pev->scale; }
inline int GetFrame( void ) { return pev->frame; } inline int GetNoise( void ) { return pev->body; }
inline int GetScrollRate( void ) { return pev->animtime; } // inline void GetColor( int r, int g, int b ) { pev->rendercolor.x = r; pev->rendercolor.y = g; pev->rendercolor.z = b; }
inline int GetBrightness( void ) { return pev->renderamt; }
// Call after you change start/end positions inline int GetFrame( void ) { return pev->frame; }
void RelinkBeam( void ); inline int GetScrollRate( void ) { return pev->animtime; }
// void SetObjectCollisionBox( void );
// Call after you change start/end positions
void DoSparks( const Vector &start, const Vector &end ); void RelinkBeam( void );
edict_t *RandomTargetname( const char *szName ); // void SetObjectCollisionBox( void );
void BeamDamage( TraceResult *ptr );
// Init after BeamCreate() void DoSparks( const Vector &start, const Vector &end );
void BeamInit( const char *pSpriteName, int width ); edict_t *RandomTargetname( const char *szName );
void PointsInit( const Vector &start, const Vector &end ); void BeamDamage( TraceResult *ptr );
void PointEntInit( const Vector &start, int endIndex ); // Init after BeamCreate()
void EntsInit( int startIndex, int endIndex ); void BeamInit( const char *pSpriteName, int width );
void HoseInit( const Vector &start, const Vector &direction ); void PointsInit( const Vector &start, const Vector &end );
void PointEntInit( const Vector &start, int endIndex );
static CMBeam *BeamCreate( const char *pSpriteName, int width ); void EntsInit( int startIndex, int endIndex );
void HoseInit( const Vector &start, const Vector &direction );
inline void LiveForTime( float time ) { SetThink(&CMBeam::SUB_Remove); pev->nextthink = gpGlobals->time + time; }
inline void BeamDamageInstant( TraceResult *ptr, float damage ) static CMBeam *BeamCreate( const char *pSpriteName, int width );
{
pev->dmg = damage; inline void LiveForTime( float time ) { SetThink(&CMBeam::SUB_Remove); pev->nextthink = gpGlobals->time + time; }
pev->dmgtime = gpGlobals->time - 1; inline void BeamDamageInstant( TraceResult *ptr, float damage )
BeamDamage(ptr); {
} pev->dmg = damage;
}; pev->dmgtime = gpGlobals->time - 1;
BeamDamage(ptr);
}
#define SF_MESSAGE_ONCE 0x0001 // Fade in, not out };
#define SF_MESSAGE_ALL 0x0002 // Send to all clients
#define SF_MESSAGE_ONCE 0x0001 // Fade in, not out
class CMLaser : public CMBeam #define SF_MESSAGE_ALL 0x0002 // Send to all clients
{
public:
void Spawn( void ); class CMLaser : public CMBeam
void Precache( void ); {
void KeyValue( KeyValueData *pkvd ); public:
void Spawn( void );
void TurnOn( void ); void Precache( void );
void TurnOff( void ); void KeyValue( KeyValueData *pkvd );
int IsOn( void );
void TurnOn( void );
void FireAtPoint( TraceResult &point ); void TurnOff( void );
int IsOn( void );
void EXPORT StrikeThink( void );
void Use( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value ); void FireAtPoint( TraceResult &point );
CMSprite *m_pSprite; void EXPORT StrikeThink( void );
int m_iszSpriteName; void Use( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value );
Vector m_firePosition;
}; CMSprite *m_pSprite;
int m_iszSpriteName;
#endif //EFFECTS_H Vector m_firePosition;
};
#endif //EFFECTS_H

View File

@@ -1,158 +1,158 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef ENGINECALLBACK_H #ifndef ENGINECALLBACK_H
#define ENGINECALLBACK_H #define ENGINECALLBACK_H
#pragma once #pragma once
#include "event_flags.h" #include "event_flags.h"
// Must be provided by user of this code // Must be provided by user of this code
extern enginefuncs_t g_engfuncs; extern enginefuncs_t g_engfuncs;
// The actual engine callbacks // The actual engine callbacks
#define GETPLAYERUSERID (*g_engfuncs.pfnGetPlayerUserId) #define GETPLAYERUSERID (*g_engfuncs.pfnGetPlayerUserId)
#define PRECACHE_MODEL (*g_engfuncs.pfnPrecacheModel) #define PRECACHE_MODEL2 (*g_engfuncs.pfnPrecacheModel)
#define PRECACHE_SOUND (*g_engfuncs.pfnPrecacheSound) #define PRECACHE_SOUND2 (*g_engfuncs.pfnPrecacheSound)
#define PRECACHE_GENERIC (*g_engfuncs.pfnPrecacheGeneric) #define PRECACHE_GENERIC (*g_engfuncs.pfnPrecacheGeneric)
#define SET_MODEL (*g_engfuncs.pfnSetModel) #define SET_MODEL2 (*g_engfuncs.pfnSetModel)
#define MODEL_INDEX (*g_engfuncs.pfnModelIndex) #define MODEL_INDEX (*g_engfuncs.pfnModelIndex)
#define MODEL_FRAMES (*g_engfuncs.pfnModelFrames) #define MODEL_FRAMES (*g_engfuncs.pfnModelFrames)
#define SET_SIZE (*g_engfuncs.pfnSetSize) #define SET_SIZE (*g_engfuncs.pfnSetSize)
#define CHANGE_LEVEL (*g_engfuncs.pfnChangeLevel) #define CHANGE_LEVEL (*g_engfuncs.pfnChangeLevel)
#define GET_SPAWN_PARMS (*g_engfuncs.pfnGetSpawnParms) #define GET_SPAWN_PARMS (*g_engfuncs.pfnGetSpawnParms)
#define SAVE_SPAWN_PARMS (*g_engfuncs.pfnSaveSpawnParms) #define SAVE_SPAWN_PARMS (*g_engfuncs.pfnSaveSpawnParms)
#define VEC_TO_YAW (*g_engfuncs.pfnVecToYaw) #define VEC_TO_YAW (*g_engfuncs.pfnVecToYaw)
#define VEC_TO_ANGLES (*g_engfuncs.pfnVecToAngles) #define VEC_TO_ANGLES (*g_engfuncs.pfnVecToAngles)
#define MOVE_TO_ORIGIN (*g_engfuncs.pfnMoveToOrigin) #define MOVE_TO_ORIGIN (*g_engfuncs.pfnMoveToOrigin)
#define oldCHANGE_YAW (*g_engfuncs.pfnChangeYaw) #define oldCHANGE_YAW (*g_engfuncs.pfnChangeYaw)
#define CHANGE_PITCH (*g_engfuncs.pfnChangePitch) #define CHANGE_PITCH (*g_engfuncs.pfnChangePitch)
#define MAKE_VECTORS (*g_engfuncs.pfnMakeVectors) #define MAKE_VECTORS (*g_engfuncs.pfnMakeVectors)
#define CREATE_ENTITY (*g_engfuncs.pfnCreateEntity) #define CREATE_ENTITY (*g_engfuncs.pfnCreateEntity)
#define REMOVE_ENTITY (*g_engfuncs.pfnRemoveEntity) #define REMOVE_ENTITY (*g_engfuncs.pfnRemoveEntity)
#define CREATE_NAMED_ENTITY (*g_engfuncs.pfnCreateNamedEntity) #define CREATE_NAMED_ENTITY (*g_engfuncs.pfnCreateNamedEntity)
#define MAKE_STATIC (*g_engfuncs.pfnMakeStatic) #define MAKE_STATIC (*g_engfuncs.pfnMakeStatic)
#define ENT_IS_ON_FLOOR (*g_engfuncs.pfnEntIsOnFloor) #define ENT_IS_ON_FLOOR (*g_engfuncs.pfnEntIsOnFloor)
#define DROP_TO_FLOOR (*g_engfuncs.pfnDropToFloor) #define DROP_TO_FLOOR (*g_engfuncs.pfnDropToFloor)
#define WALK_MOVE (*g_engfuncs.pfnWalkMove) #define WALK_MOVE (*g_engfuncs.pfnWalkMove)
#define SET_ORIGIN (*g_engfuncs.pfnSetOrigin) #define SET_ORIGIN (*g_engfuncs.pfnSetOrigin)
#define EMIT_SOUND_DYN2 (*g_engfuncs.pfnEmitSound) #define EMIT_SOUND_DYN2 (*g_engfuncs.pfnEmitSound)
#define BUILD_SOUND_MSG (*g_engfuncs.pfnBuildSoundMsg) #define BUILD_SOUND_MSG (*g_engfuncs.pfnBuildSoundMsg)
#define TRACE_LINE (*g_engfuncs.pfnTraceLine) #define TRACE_LINE (*g_engfuncs.pfnTraceLine)
#define TRACE_TOSS (*g_engfuncs.pfnTraceToss) #define TRACE_TOSS (*g_engfuncs.pfnTraceToss)
#define TRACE_MONSTER_HULL (*g_engfuncs.pfnTraceMonsterHull) #define TRACE_MONSTER_HULL (*g_engfuncs.pfnTraceMonsterHull)
#define TRACE_HULL (*g_engfuncs.pfnTraceHull) #define TRACE_HULL (*g_engfuncs.pfnTraceHull)
#define GET_AIM_VECTOR (*g_engfuncs.pfnGetAimVector) #define GET_AIM_VECTOR (*g_engfuncs.pfnGetAimVector)
#define SERVER_COMMAND (*g_engfuncs.pfnServerCommand) #define SERVER_COMMAND (*g_engfuncs.pfnServerCommand)
#define SERVER_EXECUTE (*g_engfuncs.pfnServerExecute) #define SERVER_EXECUTE (*g_engfuncs.pfnServerExecute)
#define CLIENT_COMMAND (*g_engfuncs.pfnClientCommand) #define CLIENT_COMMAND (*g_engfuncs.pfnClientCommand)
#define PARTICLE_EFFECT (*g_engfuncs.pfnParticleEffect) #define PARTICLE_EFFECT (*g_engfuncs.pfnParticleEffect)
#define LIGHT_STYLE (*g_engfuncs.pfnLightStyle) #define LIGHT_STYLE (*g_engfuncs.pfnLightStyle)
#define DECAL_INDEX (*g_engfuncs.pfnDecalIndex) #define DECAL_INDEX (*g_engfuncs.pfnDecalIndex)
#define POINT_CONTENTS (*g_engfuncs.pfnPointContents) #define POINT_CONTENTS (*g_engfuncs.pfnPointContents)
#define CRC32_INIT (*g_engfuncs.pfnCRC32_Init) #define CRC32_INIT (*g_engfuncs.pfnCRC32_Init)
#define CRC32_PROCESS_BUFFER (*g_engfuncs.pfnCRC32_ProcessBuffer) #define CRC32_PROCESS_BUFFER (*g_engfuncs.pfnCRC32_ProcessBuffer)
#define CRC32_PROCESS_BYTE (*g_engfuncs.pfnCRC32_ProcessByte) #define CRC32_PROCESS_BYTE (*g_engfuncs.pfnCRC32_ProcessByte)
#define CRC32_FINAL (*g_engfuncs.pfnCRC32_Final) #define CRC32_FINAL (*g_engfuncs.pfnCRC32_Final)
#define RANDOM_LONG (*g_engfuncs.pfnRandomLong) #define RANDOM_LONG (*g_engfuncs.pfnRandomLong)
#define RANDOM_FLOAT (*g_engfuncs.pfnRandomFloat) #define RANDOM_FLOAT (*g_engfuncs.pfnRandomFloat)
#define GETPLAYERWONID (*g_engfuncs.pfnGetPlayerWONId) #define GETPLAYERWONID (*g_engfuncs.pfnGetPlayerWONId)
inline void MESSAGE_BEGIN( int msg_dest, int msg_type, const float *pOrigin = NULL, edict_t *ed = NULL ) { inline void MESSAGE_BEGIN( int msg_dest, int msg_type, const float *pOrigin = NULL, edict_t *ed = NULL ) {
(*g_engfuncs.pfnMessageBegin)(msg_dest, msg_type, pOrigin, ed); (*g_engfuncs.pfnMessageBegin)(msg_dest, msg_type, pOrigin, ed);
} }
#define MESSAGE_END (*g_engfuncs.pfnMessageEnd) #define MESSAGE_END (*g_engfuncs.pfnMessageEnd)
#define WRITE_BYTE (*g_engfuncs.pfnWriteByte) #define WRITE_BYTE (*g_engfuncs.pfnWriteByte)
#define WRITE_CHAR (*g_engfuncs.pfnWriteChar) #define WRITE_CHAR (*g_engfuncs.pfnWriteChar)
#define WRITE_SHORT (*g_engfuncs.pfnWriteShort) #define WRITE_SHORT (*g_engfuncs.pfnWriteShort)
#define WRITE_LONG (*g_engfuncs.pfnWriteLong) #define WRITE_LONG (*g_engfuncs.pfnWriteLong)
#define WRITE_ANGLE (*g_engfuncs.pfnWriteAngle) #define WRITE_ANGLE (*g_engfuncs.pfnWriteAngle)
#define WRITE_COORD (*g_engfuncs.pfnWriteCoord) #define WRITE_COORD (*g_engfuncs.pfnWriteCoord)
#define WRITE_STRING (*g_engfuncs.pfnWriteString) #define WRITE_STRING (*g_engfuncs.pfnWriteString)
#define WRITE_ENTITY (*g_engfuncs.pfnWriteEntity) #define WRITE_ENTITY (*g_engfuncs.pfnWriteEntity)
#define CVAR_REGISTER (*g_engfuncs.pfnCVarRegister) #define CVAR_REGISTER (*g_engfuncs.pfnCVarRegister)
#define CVAR_GET_FLOAT (*g_engfuncs.pfnCVarGetFloat) #define CVAR_GET_FLOAT (*g_engfuncs.pfnCVarGetFloat)
#define CVAR_GET_STRING (*g_engfuncs.pfnCVarGetString) #define CVAR_GET_STRING (*g_engfuncs.pfnCVarGetString)
#define CVAR_SET_FLOAT (*g_engfuncs.pfnCVarSetFloat) #define CVAR_SET_FLOAT (*g_engfuncs.pfnCVarSetFloat)
#define CVAR_SET_STRING (*g_engfuncs.pfnCVarSetString) #define CVAR_SET_STRING (*g_engfuncs.pfnCVarSetString)
#define CVAR_GET_POINTER (*g_engfuncs.pfnCVarGetPointer) #define CVAR_GET_POINTER (*g_engfuncs.pfnCVarGetPointer)
#define ALERT (*g_engfuncs.pfnAlertMessage) #define ALERT (*g_engfuncs.pfnAlertMessage)
#define ENGINE_FPRINTF (*g_engfuncs.pfnEngineFprintf) #define ENGINE_FPRINTF (*g_engfuncs.pfnEngineFprintf)
#define ALLOC_PRIVATE (*g_engfuncs.pfnPvAllocEntPrivateData) #define ALLOC_PRIVATE (*g_engfuncs.pfnPvAllocEntPrivateData)
inline void *GET_PRIVATE( edict_t *pent ) inline void *GET_PRIVATE( edict_t *pent )
{ {
if ( pent ) if ( pent )
return pent->pvPrivateData; return pent->pvPrivateData;
return NULL; return NULL;
} }
#define FREE_PRIVATE (*g_engfuncs.pfnFreeEntPrivateData) #define FREE_PRIVATE (*g_engfuncs.pfnFreeEntPrivateData)
//#define STRING (*g_engfuncs.pfnSzFromIndex) //#define STRING (*g_engfuncs.pfnSzFromIndex)
#define ALLOC_STRING (*g_engfuncs.pfnAllocString) #define ALLOC_STRING (*g_engfuncs.pfnAllocString)
#define FIND_ENTITY_BY_STRING (*g_engfuncs.pfnFindEntityByString) #define FIND_ENTITY_BY_STRING (*g_engfuncs.pfnFindEntityByString)
#define GETENTITYILLUM (*g_engfuncs.pfnGetEntityIllum) #define GETENTITYILLUM (*g_engfuncs.pfnGetEntityIllum)
#define FIND_ENTITY_IN_SPHERE (*g_engfuncs.pfnFindEntityInSphere) #define FIND_ENTITY_IN_SPHERE (*g_engfuncs.pfnFindEntityInSphere)
#define FIND_CLIENT_IN_PVS (*g_engfuncs.pfnFindClientInPVS) #define FIND_CLIENT_IN_PVS (*g_engfuncs.pfnFindClientInPVS)
#define EMIT_AMBIENT_SOUND (*g_engfuncs.pfnEmitAmbientSound) #define EMIT_AMBIENT_SOUND (*g_engfuncs.pfnEmitAmbientSound)
#define GET_MODEL_PTR (*g_engfuncs.pfnGetModelPtr) #define GET_MODEL_PTR (*g_engfuncs.pfnGetModelPtr)
#define REG_USER_MSG (*g_engfuncs.pfnRegUserMsg) #define REG_USER_MSG (*g_engfuncs.pfnRegUserMsg)
#define GET_BONE_POSITION (*g_engfuncs.pfnGetBonePosition) #define GET_BONE_POSITION (*g_engfuncs.pfnGetBonePosition)
#define FUNCTION_FROM_NAME (*g_engfuncs.pfnFunctionFromName) #define FUNCTION_FROM_NAME (*g_engfuncs.pfnFunctionFromName)
#define NAME_FOR_FUNCTION (*g_engfuncs.pfnNameForFunction) #define NAME_FOR_FUNCTION (*g_engfuncs.pfnNameForFunction)
#define TRACE_TEXTURE (*g_engfuncs.pfnTraceTexture) #define TRACE_TEXTURE (*g_engfuncs.pfnTraceTexture)
#define CLIENT_PRINTF (*g_engfuncs.pfnClientPrintf) #define CLIENT_PRINTF (*g_engfuncs.pfnClientPrintf)
#define CMD_ARGS (*g_engfuncs.pfnCmd_Args) #define CMD_ARGS (*g_engfuncs.pfnCmd_Args)
#define CMD_ARGC (*g_engfuncs.pfnCmd_Argc) #define CMD_ARGC (*g_engfuncs.pfnCmd_Argc)
#define CMD_ARGV (*g_engfuncs.pfnCmd_Argv) #define CMD_ARGV (*g_engfuncs.pfnCmd_Argv)
#define GET_ATTACHMENT (*g_engfuncs.pfnGetAttachment) #define GET_ATTACHMENT (*g_engfuncs.pfnGetAttachment)
#define SET_VIEW (*g_engfuncs.pfnSetView) #define SET_VIEW (*g_engfuncs.pfnSetView)
#define SET_CROSSHAIRANGLE (*g_engfuncs.pfnCrosshairAngle) #define SET_CROSSHAIRANGLE (*g_engfuncs.pfnCrosshairAngle)
#define LOAD_FILE_FOR_ME (*g_engfuncs.pfnLoadFileForMe) #define LOAD_FILE_FOR_ME (*g_engfuncs.pfnLoadFileForMe)
#define FREE_FILE (*g_engfuncs.pfnFreeFile) #define FREE_FILE (*g_engfuncs.pfnFreeFile)
#define COMPARE_FILE_TIME (*g_engfuncs.pfnCompareFileTime) #define COMPARE_FILE_TIME (*g_engfuncs.pfnCompareFileTime)
#define GET_GAME_DIR (*g_engfuncs.pfnGetGameDir) #define GET_GAME_DIR (*g_engfuncs.pfnGetGameDir)
#define IS_MAP_VALID (*g_engfuncs.pfnIsMapValid) #define IS_MAP_VALID (*g_engfuncs.pfnIsMapValid)
#define NUMBER_OF_ENTITIES (*g_engfuncs.pfnNumberOfEntities) #define NUMBER_OF_ENTITIES (*g_engfuncs.pfnNumberOfEntities)
#define IS_DEDICATED_SERVER (*g_engfuncs.pfnIsDedicatedServer) #define IS_DEDICATED_SERVER (*g_engfuncs.pfnIsDedicatedServer)
#define PRECACHE_EVENT (*g_engfuncs.pfnPrecacheEvent) #define PRECACHE_EVENT (*g_engfuncs.pfnPrecacheEvent)
#define PLAYBACK_EVENT_FULL (*g_engfuncs.pfnPlaybackEvent) #define PLAYBACK_EVENT_FULL (*g_engfuncs.pfnPlaybackEvent)
#define ENGINE_SET_PVS (*g_engfuncs.pfnSetFatPVS) #define ENGINE_SET_PVS (*g_engfuncs.pfnSetFatPVS)
#define ENGINE_SET_PAS (*g_engfuncs.pfnSetFatPAS) #define ENGINE_SET_PAS (*g_engfuncs.pfnSetFatPAS)
#define ENGINE_CHECK_VISIBILITY (*g_engfuncs.pfnCheckVisibility) #define ENGINE_CHECK_VISIBILITY (*g_engfuncs.pfnCheckVisibility)
#define DELTA_SET ( *g_engfuncs.pfnDeltaSetField ) #define DELTA_SET ( *g_engfuncs.pfnDeltaSetField )
#define DELTA_UNSET ( *g_engfuncs.pfnDeltaUnsetField ) #define DELTA_UNSET ( *g_engfuncs.pfnDeltaUnsetField )
#define DELTA_ADDENCODER ( *g_engfuncs.pfnDeltaAddEncoder ) #define DELTA_ADDENCODER ( *g_engfuncs.pfnDeltaAddEncoder )
#define ENGINE_CURRENT_PLAYER ( *g_engfuncs.pfnGetCurrentPlayer ) #define ENGINE_CURRENT_PLAYER ( *g_engfuncs.pfnGetCurrentPlayer )
#define ENGINE_CANSKIP ( *g_engfuncs.pfnCanSkipPlayer ) #define ENGINE_CANSKIP ( *g_engfuncs.pfnCanSkipPlayer )
#define DELTA_FINDFIELD ( *g_engfuncs.pfnDeltaFindField ) #define DELTA_FINDFIELD ( *g_engfuncs.pfnDeltaFindField )
#define DELTA_SETBYINDEX ( *g_engfuncs.pfnDeltaSetFieldByIndex ) #define DELTA_SETBYINDEX ( *g_engfuncs.pfnDeltaSetFieldByIndex )
#define DELTA_UNSETBYINDEX ( *g_engfuncs.pfnDeltaUnsetFieldByIndex ) #define DELTA_UNSETBYINDEX ( *g_engfuncs.pfnDeltaUnsetFieldByIndex )
#define ENGINE_GETPHYSINFO ( *g_engfuncs.pfnGetPhysicsInfoString ) #define ENGINE_GETPHYSINFO ( *g_engfuncs.pfnGetPhysicsInfoString )
#define ENGINE_SETGROUPMASK ( *g_engfuncs.pfnSetGroupMask ) #define ENGINE_SETGROUPMASK ( *g_engfuncs.pfnSetGroupMask )
#define ENGINE_INSTANCE_BASELINE ( *g_engfuncs.pfnCreateInstancedBaseline ) #define ENGINE_INSTANCE_BASELINE ( *g_engfuncs.pfnCreateInstancedBaseline )
#define ENGINE_FORCE_UNMODIFIED ( *g_engfuncs.pfnForceUnmodified ) #define ENGINE_FORCE_UNMODIFIED ( *g_engfuncs.pfnForceUnmodified )
#define PLAYER_CNX_STATS ( *g_engfuncs.pfnGetPlayerStats ) #define PLAYER_CNX_STATS ( *g_engfuncs.pfnGetPlayerStats )
#endif //ENGINECALLBACK_H #endif //ENGINECALLBACK_H

647
src/dlls/explode.cpp Executable file → Normal file
View File

@@ -1,301 +1,346 @@
/*** /***
* *
* Copyright (c) 1996-2002, Valve LLC. All rights reserved. * Copyright (c) 1996-2002, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
/* /*
===== explode.cpp ======================================================== ===== explode.cpp ========================================================
Explosion-related code Explosion-related code
*/ */
#include "extdll.h" #include "extdll.h"
#include "util.h" #include "util.h"
#include "cmbase.h" #include "cmbase.h"
#include "cmbasemonster.h" #include "cmbasemonster.h"
#include "decals.h" #include "decals.h"
#include "explode.h" #include "explode.h"
// Spark Shower // Spark Shower
class CMShower : public CMBaseEntity class CMShower : public CMBaseEntity
{ {
void Spawn( void ); void Spawn( void );
void Think( void ); void Think( void );
void Touch( CMBaseEntity *pOther ); void Touch( CMBaseEntity *pOther );
int ObjectCaps( void ) { return FCAP_DONT_SAVE; } int ObjectCaps( void ) { return FCAP_DONT_SAVE; }
}; };
void CMShower::Spawn( void ) void CMShower::Spawn( void )
{ {
pev->velocity = RANDOM_FLOAT( 200, 300 ) * pev->angles; pev->velocity = RANDOM_FLOAT( 200, 300 ) * pev->angles;
pev->velocity.x += RANDOM_FLOAT(-100.f,100.f); pev->velocity.x += RANDOM_FLOAT(-100.f,100.f);
pev->velocity.y += RANDOM_FLOAT(-100.f,100.f); pev->velocity.y += RANDOM_FLOAT(-100.f,100.f);
if ( pev->velocity.z >= 0 ) if ( pev->velocity.z >= 0 )
pev->velocity.z += 200; pev->velocity.z += 200;
else else
pev->velocity.z -= 200; pev->velocity.z -= 200;
pev->movetype = MOVETYPE_BOUNCE; pev->movetype = MOVETYPE_BOUNCE;
pev->gravity = 0.5; pev->gravity = 0.5;
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
pev->solid = SOLID_NOT; pev->solid = SOLID_NOT;
SET_MODEL( edict(), "models/grenade.mdl"); // Need a model, just use the grenade, we don't draw it anyway SET_MODEL( edict(), "models/grenade.mdl"); // Need a model, just use the grenade, we don't draw it anyway
UTIL_SetSize(pev, g_vecZero, g_vecZero ); UTIL_SetSize(pev, g_vecZero, g_vecZero );
pev->effects |= EF_NODRAW; pev->effects |= EF_NODRAW;
pev->speed = RANDOM_FLOAT( 0.5, 1.5 ); pev->speed = RANDOM_FLOAT( 0.5, 1.5 );
pev->angles = g_vecZero; pev->angles = g_vecZero;
pev->classname = MAKE_STRING( "_spark_shower" ); pev->classname = MAKE_STRING( "spark_shower" );
} }
void CMShower::Think( void ) void CMShower::Think( void )
{ {
UTIL_Sparks( pev->origin ); UTIL_Sparks( pev->origin );
pev->speed -= 0.1; pev->speed -= 0.1;
if ( pev->speed > 0 ) if ( pev->speed > 0 )
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
else else
UTIL_Remove( this->edict() ); UTIL_Remove( this->edict() );
pev->flags &= ~FL_ONGROUND; pev->flags &= ~FL_ONGROUND;
} }
void CMShower::Touch( CMBaseEntity *pOther ) void CMShower::Touch( CMBaseEntity *pOther )
{ {
if ( pev->flags & FL_ONGROUND ) if ( pev->flags & FL_ONGROUND )
pev->velocity = pev->velocity * 0.1; pev->velocity = pev->velocity * 0.1;
else else
pev->velocity = pev->velocity * 0.6; pev->velocity = pev->velocity * 0.6;
if ( (pev->velocity.x*pev->velocity.x+pev->velocity.y*pev->velocity.y) < 10.0 ) if ( (pev->velocity.x*pev->velocity.x+pev->velocity.y*pev->velocity.y) < 10.0 )
pev->speed = 0; pev->speed = 0;
} }
class CMEnvExplosion : public CMBaseMonster // Puff of Smoke
{ class CSmoker : public CMBaseEntity
public: {
void Spawn( ); public:
void EXPORT Smoke ( void ); void Spawn( void );
void KeyValue( KeyValueData *pkvd ); void Think( void );
void DelayUse( void ); };
void Use( CMBaseEntity *pActivator, CMBaseEntity *pCaller, USE_TYPE useType, float value );
void CSmoker::Spawn( void )
int m_iMagnitude;// how large is the fireball? how much damage? {
int m_spriteScale; // what's the exact fireball sprite scale? pev->movetype = MOVETYPE_NONE;
}; pev->nextthink = gpGlobals->time;
pev->solid = SOLID_NOT;
void CMEnvExplosion::KeyValue( KeyValueData *pkvd ) UTIL_SetSize(pev, g_vecZero, g_vecZero );
{ pev->effects |= EF_NODRAW;
if (FStrEq(pkvd->szKeyName, "iMagnitude")) pev->angles = g_vecZero;
{ pev->classname = MAKE_STRING("env_smoker");
m_iMagnitude = atoi(pkvd->szValue); }
pkvd->fHandled = TRUE;
} void CSmoker::Think( void )
else {
CMBaseEntity::KeyValue( pkvd ); // lots of smoke
} MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_SMOKE );
void CMEnvExplosion::Spawn( void ) WRITE_COORD( pev->origin.x + RANDOM_FLOAT( -pev->dmg, pev->dmg ));
{ WRITE_COORD( pev->origin.y + RANDOM_FLOAT( -pev->dmg, pev->dmg ));
pev->solid = SOLID_NOT; WRITE_COORD( pev->origin.z);
pev->effects = EF_NODRAW; WRITE_SHORT( g_sModelIndexSmoke );
WRITE_BYTE( RANDOM_LONG(pev->scale, pev->scale * 1.1) );
pev->movetype = MOVETYPE_NONE; WRITE_BYTE( RANDOM_LONG(8,14) ); // framerate
/* MESSAGE_END();
if ( m_iMagnitude > 250 )
{ pev->health--;
m_iMagnitude = 250; if ( pev->health > 0 )
} pev->nextthink = gpGlobals->time + RANDOM_FLOAT(0.1, 0.2);
*/ else
UTIL_Remove( this->edict() );
float flSpriteScale; }
flSpriteScale = ( m_iMagnitude - 50) * 0.6;
// Explosion
/* class CMEnvExplosion : public CMBaseMonster
if ( flSpriteScale > 50 ) {
{ public:
flSpriteScale = 50; void Spawn( );
} void EXPORT Smoke ( void );
*/ void KeyValue( KeyValueData *pkvd );
if ( flSpriteScale < 10 ) void EXPORT DelayUse( void );
{ void Use( CMBaseEntity *pActivator, CMBaseEntity *pCaller, USE_TYPE useType, float value );
flSpriteScale = 10;
} int m_iMagnitude;// how large is the fireball? how much damage?
int m_spriteScale; // what's the exact fireball sprite scale?
m_spriteScale = (int)flSpriteScale; };
pev->classname = MAKE_STRING( "_env_explosion" );
} void CMEnvExplosion::KeyValue( KeyValueData *pkvd )
{
void CMEnvExplosion::DelayUse( void ) if (FStrEq(pkvd->szKeyName, "iMagnitude"))
{ {
Use( NULL, NULL, USE_TOGGLE, 0 ); m_iMagnitude = atoi(pkvd->szValue);
} pkvd->fHandled = TRUE;
}
void CMEnvExplosion::Use( CMBaseEntity *pActivator, CMBaseEntity *pCaller, USE_TYPE useType, float value ) else
{ CMBaseEntity::KeyValue( pkvd );
TraceResult tr; }
pev->model = iStringNull;//invisible void CMEnvExplosion::Spawn( void )
pev->solid = SOLID_NOT;// intangible {
pev->solid = SOLID_NOT;
Vector vecSpot;// trace starts here! pev->effects = EF_NODRAW;
vecSpot = pev->origin + Vector ( 0 , 0 , 8 ); pev->movetype = MOVETYPE_NONE;
/*
UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -40 ), ignore_monsters, ENT(pev), & tr); if ( m_iMagnitude > 250 )
{
// Pull out of the wall a bit m_iMagnitude = 250;
if ( tr.flFraction != 1.0 ) }
{ */
pev->origin = tr.vecEndPos + (tr.vecPlaneNormal * (m_iMagnitude - 24) * 0.6);
} float flSpriteScale;
else flSpriteScale = ( m_iMagnitude - 50) * 0.6;
{
pev->origin = pev->origin; /*
} if ( flSpriteScale > 50 )
{
// draw decal flSpriteScale = 50;
if (! ( pev->spawnflags & SF_ENVEXPLOSION_NODECAL)) }
{ */
if ( RANDOM_FLOAT( 0 , 1 ) < 0.5 ) if ( flSpriteScale < 10 )
{ {
UTIL_DecalTrace( &tr, DECAL_SCORCH1 ); flSpriteScale = 10;
} }
else
{ m_spriteScale = (int)flSpriteScale;
UTIL_DecalTrace( &tr, DECAL_SCORCH2 ); pev->classname = MAKE_STRING( "env_explosion" );
} }
}
void CMEnvExplosion::DelayUse( void )
// draw fireball {
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOFIREBALL ) ) Use( NULL, NULL, USE_TOGGLE, 0 );
{ }
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_EXPLOSION); void CMEnvExplosion::Use( CMBaseEntity *pActivator, CMBaseEntity *pCaller, USE_TYPE useType, float value )
WRITE_COORD( pev->origin.x ); {
WRITE_COORD( pev->origin.y ); TraceResult tr;
WRITE_COORD( pev->origin.z );
WRITE_SHORT( g_sModelIndexFireball ); pev->model = iStringNull;//invisible
WRITE_BYTE( (BYTE)m_spriteScale ); // scale * 10 pev->solid = SOLID_NOT;// intangible
WRITE_BYTE( 15 ); // framerate
WRITE_BYTE( TE_EXPLFLAG_NONE ); Vector vecSpot;// trace starts here!
MESSAGE_END();
} vecSpot = pev->origin + Vector ( 0 , 0 , 8 );
else
{ UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -40 ), ignore_monsters, ENT(pev), & tr);
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_EXPLOSION); // Pull out of the wall a bit
WRITE_COORD( pev->origin.x ); if ( tr.flFraction != 1.0 )
WRITE_COORD( pev->origin.y ); {
WRITE_COORD( pev->origin.z ); pev->origin = tr.vecEndPos + (tr.vecPlaneNormal * (m_iMagnitude - 24) * 0.6);
WRITE_SHORT( g_sModelIndexFireball ); }
WRITE_BYTE( 0 ); // no sprite else
WRITE_BYTE( 15 ); // framerate {
WRITE_BYTE( TE_EXPLFLAG_NONE ); pev->origin = pev->origin;
MESSAGE_END(); }
}
// draw decal
// do damage if (! ( pev->spawnflags & SF_ENVEXPLOSION_NODECAL))
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NODAMAGE ) ) {
{ if ( RANDOM_FLOAT( 0 , 1 ) < 0.5 )
RadiusDamage ( pev, pev->owner == NULL ? pev : VARS( pev->owner ), m_iMagnitude, CLASS_NONE, DMG_BLAST ); {
} UTIL_DecalTrace( &tr, DECAL_SCORCH1 );
}
SetThink( &CMEnvExplosion::Smoke ); else
pev->nextthink = gpGlobals->time + 0.3; {
UTIL_DecalTrace( &tr, DECAL_SCORCH2 );
// draw sparks }
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOSPARKS ) ) }
{
int sparkCount = RANDOM_LONG(0,3); // draw fireball
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOFIREBALL ) )
for ( int i = 0; i < sparkCount; i++ ) {
{ MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
CMBaseEntity *pSpark = CreateClassPtr((CMShower *)NULL); WRITE_BYTE( TE_EXPLOSION);
if ( pSpark == NULL ) WRITE_COORD( pev->origin.x );
{ WRITE_COORD( pev->origin.y );
ALERT( at_console, "Failed to spawn spark_shower!" ); WRITE_COORD( pev->origin.z );
} WRITE_SHORT( g_sModelIndexFireball );
else WRITE_BYTE( (BYTE)m_spriteScale ); // scale * 10
{ WRITE_BYTE( 15 ); // framerate
UTIL_SetOrigin( pSpark->pev, pev->origin ); WRITE_BYTE( TE_EXPLFLAG_NONE );
pSpark->pev->angles = tr.vecPlaneNormal; MESSAGE_END();
pSpark->Spawn(); }
} else
// Create( "spark_shower", pev->origin, tr.vecPlaneNormal, NULL ); {
} MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
} WRITE_BYTE( TE_EXPLOSION);
} WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
void CMEnvExplosion::Smoke( void ) WRITE_COORD( pev->origin.z );
{ WRITE_SHORT( g_sModelIndexFireball );
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOSMOKE ) ) WRITE_BYTE( 0 ); // no sprite
{ WRITE_BYTE( 15 ); // framerate
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin ); WRITE_BYTE( TE_EXPLFLAG_NONE );
WRITE_BYTE( TE_SMOKE ); MESSAGE_END();
WRITE_COORD( pev->origin.x ); }
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z ); // do damage
WRITE_SHORT( g_sModelIndexSmoke ); if ( !( pev->spawnflags & SF_ENVEXPLOSION_NODAMAGE ) )
WRITE_BYTE( (BYTE)m_spriteScale ); // scale * 10 {
WRITE_BYTE( 12 ); // framerate RadiusDamage ( pev, pev->owner == NULL ? pev : VARS( pev->owner ), m_iMagnitude, CLASS_NONE, DMG_BLAST );
MESSAGE_END(); }
}
SetThink( &CMEnvExplosion::Smoke );
if ( !(pev->spawnflags & SF_ENVEXPLOSION_REPEATABLE) ) pev->nextthink = gpGlobals->time + 0.3;
{
UTIL_Remove( this->edict() ); // draw sparks
} if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOSPARKS ) )
} {
int sparkCount = RANDOM_LONG(0,3);
// Stock to quickly create a one-time explosion for ( int i = 0; i < sparkCount; i++ )
void ExplosionCreate( const Vector &center, const Vector &angles, edict_t *pOwner, int magnitude, int flags, float delay ) {
{ CMBaseEntity *pSpark = CreateClassPtr((CMShower *)NULL);
KeyValueData kvd; if ( pSpark == NULL )
char buf[128]; {
ALERT( at_console, "Failed to spawn spark_shower!" );
//CMBaseEntity *pExplosion = CMBaseEntity::Create( "env_explosion", center, angles, pOwner ); }
CMBaseEntity *pExplosion = CreateClassPtr((CMEnvExplosion *)NULL); else
if ( pExplosion == NULL ) {
{ UTIL_SetOrigin( pSpark->pev, pev->origin );
ALERT( at_console, "Failed to create env_explosion!" ); pSpark->pev->angles = tr.vecPlaneNormal;
} pSpark->Spawn();
else }
{ // Create( "spark_shower", pev->origin, tr.vecPlaneNormal, NULL );
sprintf( buf, "%3d", magnitude ); }
kvd.szKeyName = "iMagnitude"; }
kvd.szValue = buf; }
pExplosion->KeyValue( &kvd );
pExplosion->pev->owner = pOwner; void CMEnvExplosion::Smoke( void )
pExplosion->pev->spawnflags |= flags; {
if ( !( pev->spawnflags & SF_ENVEXPLOSION_NOSMOKE ) )
UTIL_SetOrigin( pExplosion->pev, center ); {
pExplosion->pev->angles = angles; MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_SMOKE );
// This is a temporary entity, filter out the flag WRITE_COORD( pev->origin.x );
pExplosion->pev->spawnflags &= ~SF_ENVEXPLOSION_REPEATABLE; WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
pExplosion->Spawn(); WRITE_SHORT( g_sModelIndexSmoke );
if ( delay > 0.0f ) WRITE_BYTE( (BYTE)m_spriteScale ); // scale * 10
{ WRITE_BYTE( 12 ); // framerate
//pExplosion->SetThink( &CMBaseEntity::SUB_CallUseToggle ); // i don't trust you MESSAGE_END();
pExplosion->SetThink( &CMEnvExplosion::DelayUse ); }
pExplosion->pev->nextthink = gpGlobals->time + delay;
} if ( !(pev->spawnflags & SF_ENVEXPLOSION_REPEATABLE) )
else {
{ UTIL_Remove( this->edict() );
pExplosion->Use( NULL, NULL, USE_TOGGLE, 0 ); }
} }
}
}
// Stocks:
// Create a one-time explosion
void ExplosionCreate( const Vector &center, const Vector &angles, edict_t *pOwner, int magnitude, int flags, float delay )
{
KeyValueData kvd;
char buf[128];
//CMBaseEntity *pExplosion = CMBaseEntity::Create( "env_explosion", center, angles, pOwner );
CMBaseEntity *pExplosion = CreateClassPtr((CMEnvExplosion *)NULL);
if ( pExplosion == NULL )
{
ALERT( at_console, "Failed to create env_explosion!" );
}
else
{
sprintf( buf, "%3d", magnitude );
kvd.szKeyName = "iMagnitude";
kvd.szValue = buf;
pExplosion->KeyValue( &kvd );
pExplosion->pev->owner = pOwner;
pExplosion->pev->spawnflags |= flags;
UTIL_SetOrigin( pExplosion->pev, center );
pExplosion->pev->angles = angles;
// This is a temporary entity, filter out the flag
pExplosion->pev->spawnflags &= ~SF_ENVEXPLOSION_REPEATABLE;
pExplosion->Spawn();
pExplosion->SetThink( &CMEnvExplosion::DelayUse );
pExplosion->pev->nextthink = gpGlobals->time + delay;
}
}
// Emit smoke
void SmokeCreate( const Vector &origin, int amount, int size, int radius, float delay )
{
CMBaseEntity *pSmoker = CreateClassPtr((CSmoker *)NULL); // CMBaseEntity::Create( "env_smoker", pev->origin, g_vecZero, NULL );
UTIL_SetOrigin( pSmoker->pev, origin );
pSmoker->Spawn();
pSmoker->pev->health = amount; // number of smoke balls
pSmoker->pev->scale = size; // size in 0.1x - size 10 = x1.0
pSmoker->pev->dmg = radius; // radial distribution
pSmoker->pev->nextthink = gpGlobals->time + delay; // Start in ... seconds
}

View File

@@ -1,32 +1,33 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef EXPLODE_H #ifndef EXPLODE_H
#define EXPLODE_H #define EXPLODE_H
#define SF_ENVEXPLOSION_NODAMAGE ( 1 << 0 ) // when set, ENV_EXPLOSION will not actually inflict damage #define SF_ENVEXPLOSION_NODAMAGE ( 1 << 0 ) // when set, ENV_EXPLOSION will not actually inflict damage
#define SF_ENVEXPLOSION_REPEATABLE ( 1 << 1 ) // can this entity be refired? #define SF_ENVEXPLOSION_REPEATABLE ( 1 << 1 ) // can this entity be refired?
#define SF_ENVEXPLOSION_NOFIREBALL ( 1 << 2 ) // don't draw the fireball #define SF_ENVEXPLOSION_NOFIREBALL ( 1 << 2 ) // don't draw the fireball
#define SF_ENVEXPLOSION_NOSMOKE ( 1 << 3 ) // don't draw the smoke #define SF_ENVEXPLOSION_NOSMOKE ( 1 << 3 ) // don't draw the smoke
#define SF_ENVEXPLOSION_NODECAL ( 1 << 4 ) // don't make a scorch mark #define SF_ENVEXPLOSION_NODECAL ( 1 << 4 ) // don't make a scorch mark
#define SF_ENVEXPLOSION_NOSPARKS ( 1 << 5 ) // don't make a scorch mark #define SF_ENVEXPLOSION_NOSPARKS ( 1 << 5 ) // don't make a scorch mark
extern DLL_GLOBAL short g_sModelIndexFireball; extern DLL_GLOBAL short g_sModelIndexFireball;
extern DLL_GLOBAL short g_sModelIndexSmoke; extern DLL_GLOBAL short g_sModelIndexSmoke;
extern DLL_GLOBAL short g_sModelIndexTinySpit;
extern void ExplosionCreate( const Vector &center, const Vector &angles, edict_t *pOwner, int magnitude, int flags, float delay ); extern void ExplosionCreate( const Vector &center, const Vector &angles, edict_t *pOwner, int magnitude, int flags, float delay );
extern void SmokeCreate( const Vector &origin, int amount, int size, int radius, float delay );
#endif //EXPLODE_H
#endif //EXPLODE_H

View File

@@ -1,87 +1,91 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef EXTDLL_H #ifndef EXTDLL_H
#define EXTDLL_H #define EXTDLL_H
// //
// Global header file for extension DLLs // Global header file for extension DLLs
// //
// Allow "DEBUG" in addition to default "_DEBUG" // Allow "DEBUG" in addition to default "_DEBUG"
#ifdef _DEBUG #ifdef _DEBUG
#define DEBUG 1 #define DEBUG 1
#endif #endif
// Silence certain warnings // Silence certain warnings
#pragma warning(disable : 4244) // int or float down-conversion // PS: All warnings to be silenced until T5 milestone. -Giegue
#pragma warning(disable : 4305) // int or float data truncation #pragma warning(disable : 4244) // int or float down-conversion
#pragma warning(disable : 4201) // nameless struct/union #pragma warning(disable : 4305) // int or float data truncation
#pragma warning(disable : 4514) // unreferenced inline function removed #pragma warning(disable : 4201) // nameless struct/union
#pragma warning(disable : 4100) // unreferenced formal parameter #pragma warning(disable : 4514) // unreferenced inline function removed
#pragma warning(disable : 4100) // unreferenced formal parameter
// Prevent tons of unused windows definitions #pragma warning(disable : 4390) // empty controlled statement (seems to work fine? monster_api.cpp[101/115])
#ifdef _WIN32 #pragma warning(disable : 4091) // nameless typedef
#define WIN32_LEAN_AND_MEAN #pragma warning(disable : 4996) // unsafe string operations
#define NOWINRES
#define NOSERVICE // Prevent tons of unused windows definitions
#define NOMCX #ifdef _WIN32
#define NOIME #define WIN32_LEAN_AND_MEAN
#include "windows.h" #define NOWINRES
#else // _WIN32 #define NOSERVICE
#define FALSE 0 #define NOMCX
#define TRUE (!FALSE) #define NOIME
typedef unsigned long ULONG; #include "windows.h"
typedef unsigned char BYTE; #else // _WIN32
typedef int BOOL; #define FALSE 0
#define MAX_PATH PATH_MAX #define TRUE (!FALSE)
#include <limits.h> typedef unsigned long ULONG;
#include <stdarg.h> typedef unsigned char BYTE;
#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) typedef int BOOL;
#endif //_WIN32 #define MAX_PATH PATH_MAX
#include <limits.h>
// Misc C-runtime library headers #include <stdarg.h>
#include "stdio.h" #define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
#include "stdlib.h" #endif //_WIN32
#include "math.h"
// Misc C-runtime library headers
// min/max is not on math.h library #include "stdio.h"
// move outside win32 scope so it can compile on both platforms #include "stdlib.h"
#define min(a,b) (((a) < (b)) ? (a) : (b)) #include "math.h"
#define max(a,b) (((a) > (b)) ? (a) : (b))
// min/max is not on math.h library
// Header file containing definition of globalvars_t and entvars_t // move outside win32 scope so it can compile on both platforms
typedef int func_t; // #define min(a,b) (((a) < (b)) ? (a) : (b))
typedef int string_t; // from engine's pr_comp.h; #define max(a,b) (((a) > (b)) ? (a) : (b))
typedef float vec_t; // needed before including progdefs.h
// Header file containing definition of globalvars_t and entvars_t
// Vector class typedef int func_t; //
#include "vector.h" typedef int string_t; // from engine's pr_comp.h;
typedef float vec_t; // needed before including progdefs.h
// Defining it as a (bogus) struct helps enforce type-checking
#define vec3_t Vector // Vector class
#include "vector.h"
// Shared engine/DLL constants
#include "const.h" // Defining it as a (bogus) struct helps enforce type-checking
#include "progdefs.h" #define vec3_t Vector
#include "edict.h"
// Shared engine/DLL constants
// Shared header describing protocol between engine and DLLs #include "const.h"
#include "eiface.h" #include "progdefs.h"
#include "edict.h"
// Shared header between the client DLL and the game DLLs
#include "cdll_dll.h" // Shared header describing protocol between engine and DLLs
#include "eiface.h"
#endif //EXTDLL_H
// Shared header between the client DLL and the game DLLs
#include "cdll_dll.h"
#endif //EXTDLL_H

View File

@@ -1,281 +1,280 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* This source code contains proprietary and confidential information of * This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to * Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access, * persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal. * use or distribution of this code by or to any unlicensed person is illegal.
* *
****/ ****/
#include "extdll.h" #include "extdll.h"
#include "util.h" #include "util.h"
#include "cmbase.h" #include "cmbase.h"
#include "cmbasemonster.h" #include "cmbasemonster.h"
#include "monsters.h" #include "cmflyingmonster.h"
#include "schedule.h" #include "monsters.h"
#include "schedule.h"
#define FLYING_AE_FLAP (8)
#define FLYING_AE_FLAPSOUND (9) #define FLYING_AE_FLAP (8)
#define FLYING_AE_FLAPSOUND (9)
extern DLL_GLOBAL edict_t *g_pBodyQueueHead;
int CMFlyingMonster :: CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, edict_t *pTarget, float *pflDist )
int CMFlyingMonster :: CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, edict_t *pTarget, float *pflDist ) {
{ // UNDONE: need to check more than the endpoint
// UNDONE: need to check more than the endpoint if (FBitSet(pev->flags, FL_SWIM) && (UTIL_PointContents(vecEnd) != CONTENTS_WATER))
if (FBitSet(pev->flags, FL_SWIM) && (UTIL_PointContents(vecEnd) != CONTENTS_WATER)) {
{ // ALERT(at_aiconsole, "can't swim out of water\n");
// ALERT(at_aiconsole, "can't swim out of water\n"); return FALSE;
return FALSE; }
}
TraceResult tr;
TraceResult tr;
UTIL_TraceHull( vecStart + Vector( 0, 0, 32 ), vecEnd + Vector( 0, 0, 32 ), dont_ignore_monsters, large_hull, edict(), &tr );
UTIL_TraceHull( vecStart + Vector( 0, 0, 32 ), vecEnd + Vector( 0, 0, 32 ), dont_ignore_monsters, large_hull, edict(), &tr );
// ALERT( at_console, "%.0f %.0f %.0f : ", vecStart.x, vecStart.y, vecStart.z );
// ALERT( at_console, "%.0f %.0f %.0f : ", vecStart.x, vecStart.y, vecStart.z ); // ALERT( at_console, "%.0f %.0f %.0f\n", vecEnd.x, vecEnd.y, vecEnd.z );
// ALERT( at_console, "%.0f %.0f %.0f\n", vecEnd.x, vecEnd.y, vecEnd.z );
if (pflDist)
if (pflDist) {
{ *pflDist = ( (tr.vecEndPos - Vector( 0, 0, 32 )) - vecStart ).Length();// get the distance.
*pflDist = ( (tr.vecEndPos - Vector( 0, 0, 32 )) - vecStart ).Length();// get the distance. }
}
// ALERT( at_console, "check %d %d %f\n", tr.fStartSolid, tr.fAllSolid, tr.flFraction );
// ALERT( at_console, "check %d %d %f\n", tr.fStartSolid, tr.fAllSolid, tr.flFraction ); if (tr.fStartSolid || tr.flFraction < 1.0)
if (tr.fStartSolid || tr.flFraction < 1.0) {
{ if ( pTarget && (pTarget == gpGlobals->trace_ent) )
if ( pTarget && (pTarget == gpGlobals->trace_ent) ) return LOCALMOVE_VALID;
return LOCALMOVE_VALID; return LOCALMOVE_INVALID;
return LOCALMOVE_INVALID; }
}
return LOCALMOVE_VALID;
return LOCALMOVE_VALID; }
}
BOOL CMFlyingMonster :: FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, edict_t *pTargetEnt, Vector *pApex )
BOOL CMFlyingMonster :: FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, edict_t *pTargetEnt, Vector *pApex ) {
{ return CMBaseMonster::FTriangulate( vecStart, vecEnd, flDist, pTargetEnt, pApex );
return CMBaseMonster::FTriangulate( vecStart, vecEnd, flDist, pTargetEnt, pApex ); }
}
Activity CMFlyingMonster :: GetStoppedActivity( void )
Activity CMFlyingMonster :: GetStoppedActivity( void ) {
{ if ( pev->movetype != MOVETYPE_FLY ) // UNDONE: Ground idle here, IDLE may be something else
if ( pev->movetype != MOVETYPE_FLY ) // UNDONE: Ground idle here, IDLE may be something else return ACT_IDLE;
return ACT_IDLE;
return ACT_HOVER;
return ACT_HOVER; }
}
void CMFlyingMonster :: Stop( void )
void CMFlyingMonster :: Stop( void ) {
{ Activity stopped = GetStoppedActivity();
Activity stopped = GetStoppedActivity(); if ( m_IdealActivity != stopped )
if ( m_IdealActivity != stopped ) {
{ m_flightSpeed = 0;
m_flightSpeed = 0; m_IdealActivity = stopped;
m_IdealActivity = stopped; }
} pev->angles.z = 0;
pev->angles.z = 0; pev->angles.x = 0;
pev->angles.x = 0; m_vecTravel = g_vecZero;
m_vecTravel = g_vecZero; }
}
float CMFlyingMonster :: ChangeYaw( int speed )
float CMFlyingMonster :: ChangeYaw( int speed ) {
{ if ( pev->movetype == MOVETYPE_FLY )
if ( pev->movetype == MOVETYPE_FLY ) {
{ float diff = FlYawDiff();
float diff = FlYawDiff(); float target = 0;
float target = 0;
if ( m_IdealActivity != GetStoppedActivity() )
if ( m_IdealActivity != GetStoppedActivity() ) {
{ if ( diff < -20 )
if ( diff < -20 ) target = 90;
target = 90; else if ( diff > 20 )
else if ( diff > 20 ) target = -90;
target = -90; }
} pev->angles.z = UTIL_Approach( target, pev->angles.z, 220.0 * gpGlobals->frametime );
pev->angles.z = UTIL_Approach( target, pev->angles.z, 220.0 * gpGlobals->frametime ); }
} return CMBaseMonster::ChangeYaw( speed );
return CMBaseMonster::ChangeYaw( speed ); }
}
void CMFlyingMonster :: Killed( entvars_t *pevAttacker, int iGib )
void CMFlyingMonster :: Killed( entvars_t *pevAttacker, int iGib ) {
{ pev->movetype = MOVETYPE_STEP;
pev->movetype = MOVETYPE_STEP; ClearBits( pev->flags, FL_ONGROUND );
ClearBits( pev->flags, FL_ONGROUND ); pev->angles.z = 0;
pev->angles.z = 0; pev->angles.x = 0;
pev->angles.x = 0; CMBaseMonster::Killed( pevAttacker, iGib );
CMBaseMonster::Killed( pevAttacker, iGib ); }
}
void CMFlyingMonster :: HandleAnimEvent( MonsterEvent_t *pEvent )
void CMFlyingMonster :: HandleAnimEvent( MonsterEvent_t *pEvent ) {
{ switch( pEvent->event )
switch( pEvent->event ) {
{ case FLYING_AE_FLAP:
case FLYING_AE_FLAP: m_flightSpeed = 400;
m_flightSpeed = 400; break;
break;
case FLYING_AE_FLAPSOUND:
case FLYING_AE_FLAPSOUND: if ( m_pFlapSound )
if ( m_pFlapSound ) EMIT_SOUND( edict(), CHAN_BODY, m_pFlapSound, 1, ATTN_NORM );
EMIT_SOUND( edict(), CHAN_BODY, m_pFlapSound, 1, ATTN_NORM ); break;
break;
default:
default: CMBaseMonster::HandleAnimEvent( pEvent );
CMBaseMonster::HandleAnimEvent( pEvent ); break;
break; }
} }
}
void CMFlyingMonster :: Move( float flInterval )
void CMFlyingMonster :: Move( float flInterval ) {
{ if ( pev->movetype == MOVETYPE_FLY )
if ( pev->movetype == MOVETYPE_FLY ) m_flGroundSpeed = m_flightSpeed;
m_flGroundSpeed = m_flightSpeed; CMBaseMonster::Move( flInterval );
CMBaseMonster::Move( flInterval ); }
}
BOOL CMFlyingMonster:: ShouldAdvanceRoute( float flWaypointDist )
BOOL CMFlyingMonster:: ShouldAdvanceRoute( float flWaypointDist ) {
{ // Get true 3D distance to the goal so we actually reach the correct height
// Get true 3D distance to the goal so we actually reach the correct height if ( m_Route[ m_iRouteIndex ].iType & bits_MF_IS_GOAL )
if ( m_Route[ m_iRouteIndex ].iType & bits_MF_IS_GOAL ) flWaypointDist = ( m_Route[ m_iRouteIndex ].vecLocation - pev->origin ).Length();
flWaypointDist = ( m_Route[ m_iRouteIndex ].vecLocation - pev->origin ).Length();
if ( flWaypointDist <= 64 + (m_flGroundSpeed * gpGlobals->frametime) )
if ( flWaypointDist <= 64 + (m_flGroundSpeed * gpGlobals->frametime) ) return TRUE;
return TRUE;
return FALSE;
return FALSE; }
}
void CMFlyingMonster::MoveExecute( edict_t *pTargetEnt, const Vector &vecDir, float flInterval )
void CMFlyingMonster::MoveExecute( edict_t *pTargetEnt, const Vector &vecDir, float flInterval ) {
{ if ( pev->movetype == MOVETYPE_FLY )
if ( pev->movetype == MOVETYPE_FLY ) {
{ if ( gpGlobals->time - m_stopTime > 1.0 )
if ( gpGlobals->time - m_stopTime > 1.0 ) {
{ if ( m_IdealActivity != m_movementActivity )
if ( m_IdealActivity != m_movementActivity ) {
{ m_IdealActivity = m_movementActivity;
m_IdealActivity = m_movementActivity; m_flGroundSpeed = m_flightSpeed = 200;
m_flGroundSpeed = m_flightSpeed = 200; }
} }
} Vector vecMove = pev->origin + (( vecDir + (m_vecTravel * m_momentum) ).Normalize() * (m_flGroundSpeed * flInterval));
Vector vecMove = pev->origin + (( vecDir + (m_vecTravel * m_momentum) ).Normalize() * (m_flGroundSpeed * flInterval));
if ( m_IdealActivity != m_movementActivity )
if ( m_IdealActivity != m_movementActivity ) {
{ m_flightSpeed = UTIL_Approach( 100, m_flightSpeed, 75 * gpGlobals->frametime );
m_flightSpeed = UTIL_Approach( 100, m_flightSpeed, 75 * gpGlobals->frametime ); if ( m_flightSpeed < 100 )
if ( m_flightSpeed < 100 ) m_stopTime = gpGlobals->time;
m_stopTime = gpGlobals->time; }
} else
else m_flightSpeed = UTIL_Approach( 20, m_flightSpeed, 300 * gpGlobals->frametime );
m_flightSpeed = UTIL_Approach( 20, m_flightSpeed, 300 * gpGlobals->frametime );
if ( CheckLocalMove ( pev->origin, vecMove, pTargetEnt, NULL ) )
if ( CheckLocalMove ( pev->origin, vecMove, pTargetEnt, NULL ) ) {
{ m_vecTravel = (vecMove - pev->origin);
m_vecTravel = (vecMove - pev->origin); m_vecTravel = m_vecTravel.Normalize();
m_vecTravel = m_vecTravel.Normalize(); UTIL_MoveToOrigin(ENT(pev), vecMove, (m_flGroundSpeed * flInterval), MOVE_STRAFE);
UTIL_MoveToOrigin(ENT(pev), vecMove, (m_flGroundSpeed * flInterval), MOVE_STRAFE); }
} else
else {
{ m_IdealActivity = GetStoppedActivity();
m_IdealActivity = GetStoppedActivity(); m_stopTime = gpGlobals->time;
m_stopTime = gpGlobals->time; m_vecTravel = g_vecZero;
m_vecTravel = g_vecZero; }
} }
} else
else CMBaseMonster::MoveExecute( pTargetEnt, vecDir, flInterval );
CMBaseMonster::MoveExecute( pTargetEnt, vecDir, flInterval ); }
}
float CMFlyingMonster::CeilingZ( const Vector &position )
float CMFlyingMonster::CeilingZ( const Vector &position ) {
{ TraceResult tr;
TraceResult tr;
Vector minUp = position;
Vector minUp = position; Vector maxUp = position;
Vector maxUp = position; maxUp.z += 4096.0;
maxUp.z += 4096.0;
UTIL_TraceLine(position, maxUp, ignore_monsters, NULL, &tr);
UTIL_TraceLine(position, maxUp, ignore_monsters, NULL, &tr); if (tr.flFraction != 1.0)
if (tr.flFraction != 1.0) maxUp.z = tr.vecEndPos.z;
maxUp.z = tr.vecEndPos.z;
if ((pev->flags) & FL_SWIM)
if ((pev->flags) & FL_SWIM) {
{ return UTIL_WaterLevel( position, minUp.z, maxUp.z );
return UTIL_WaterLevel( position, minUp.z, maxUp.z ); }
} return maxUp.z;
return maxUp.z; }
}
BOOL CMFlyingMonster::ProbeZ( const Vector &position, const Vector &probe, float *pFraction)
BOOL CMFlyingMonster::ProbeZ( const Vector &position, const Vector &probe, float *pFraction) {
{ int conPosition = UTIL_PointContents(position);
int conPosition = UTIL_PointContents(position); if ( (((pev->flags) & FL_SWIM) == FL_SWIM) ^ (conPosition == CONTENTS_WATER))
if ( (((pev->flags) & FL_SWIM) == FL_SWIM) ^ (conPosition == CONTENTS_WATER)) {
{ // SWIMING & !WATER
// SWIMING & !WATER // or FLYING & WATER
// or FLYING & WATER //
// *pFraction = 0.0;
*pFraction = 0.0; return TRUE; // We hit a water boundary because we are where we don't belong.
return TRUE; // We hit a water boundary because we are where we don't belong. }
} int conProbe = UTIL_PointContents(probe);
int conProbe = UTIL_PointContents(probe); if (conProbe == conPosition)
if (conProbe == conPosition) {
{ // The probe is either entirely inside the water (for fish) or entirely
// The probe is either entirely inside the water (for fish) or entirely // outside the water (for birds).
// outside the water (for birds). //
// *pFraction = 1.0;
*pFraction = 1.0; return FALSE;
return FALSE; }
}
Vector ProbeUnit = (probe-position).Normalize();
Vector ProbeUnit = (probe-position).Normalize(); float ProbeLength = (probe-position).Length();
float ProbeLength = (probe-position).Length(); float maxProbeLength = ProbeLength;
float maxProbeLength = ProbeLength; float minProbeLength = 0;
float minProbeLength = 0;
float diff = maxProbeLength - minProbeLength;
float diff = maxProbeLength - minProbeLength; while (diff > 1.0)
while (diff > 1.0) {
{ float midProbeLength = minProbeLength + diff/2.0;
float midProbeLength = minProbeLength + diff/2.0; Vector midProbeVec = midProbeLength * ProbeUnit;
Vector midProbeVec = midProbeLength * ProbeUnit; if (UTIL_PointContents(position+midProbeVec) == conPosition)
if (UTIL_PointContents(position+midProbeVec) == conPosition) {
{ minProbeLength = midProbeLength;
minProbeLength = midProbeLength; }
} else
else {
{ maxProbeLength = midProbeLength;
maxProbeLength = midProbeLength; }
} diff = maxProbeLength - minProbeLength;
diff = maxProbeLength - minProbeLength; }
} *pFraction = minProbeLength/ProbeLength;
*pFraction = minProbeLength/ProbeLength;
return TRUE;
return TRUE; }
}
float CMFlyingMonster::FloorZ( const Vector &position )
float CMFlyingMonster::FloorZ( const Vector &position ) {
{ TraceResult tr;
TraceResult tr;
Vector down = position;
Vector down = position; down.z -= 2048;
down.z -= 2048;
UTIL_TraceLine( position, down, ignore_monsters, NULL, &tr );
UTIL_TraceLine( position, down, ignore_monsters, NULL, &tr );
if ( tr.flFraction != 1.0 )
if ( tr.flFraction != 1.0 ) return tr.vecEndPos.z;
return tr.vecEndPos.z;
return down.z;
return down.z; }
}

View File

@@ -1,70 +1,70 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef FUNC_BREAK_H #ifndef FUNC_BREAK_H
#define FUNC_BREAK_H #define FUNC_BREAK_H
typedef enum { expRandom, expDirected} Explosions; typedef enum { expRandom, expDirected} Explosions;
typedef enum { matGlass = 0, matWood, matMetal, matFlesh, matCinderBlock, matCeilingTile, matComputer, matUnbreakableGlass, matRocks, matNone, matLastMaterial } Materials; typedef enum { matGlass = 0, matWood, matMetal, matFlesh, matCinderBlock, matCeilingTile, matComputer, matUnbreakableGlass, matRocks, matNone, matLastMaterial } Materials;
#define NUM_SHARDS 6 // this many shards spawned when breakable objects break; #define NUM_SHARDS 6 // this many shards spawned when breakable objects break;
class CMBreakable : public CMBaseDelay class CMBreakable : public CMBaseDelay
{ {
public: public:
// basic functions // basic functions
void Spawn( void ); void Spawn( void );
void Precache( void ); void Precache( void );
void KeyValue( KeyValueData* pkvd); void KeyValue( KeyValueData* pkvd);
void EXPORT BreakTouch( CMBaseEntity *pOther ); void EXPORT BreakTouch( CMBaseEntity *pOther );
void Use( CMBaseEntity *pActivator, CMBaseEntity *pCaller, USE_TYPE useType, float value ); void Use( CMBaseEntity *pActivator, CMBaseEntity *pCaller, USE_TYPE useType, float value );
void DamageSound( void ); void DamageSound( void );
// breakables use an overridden takedamage // breakables use an overridden takedamage
virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ); virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType );
// To spark when hit // To spark when hit
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ); void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType );
BOOL IsBreakable( void ); BOOL IsBreakable( void );
BOOL SparkWhenHit( void ); BOOL SparkWhenHit( void );
int DamageDecal( int bitsDamageType ); int DamageDecal( int bitsDamageType );
void EXPORT Die( void ); void EXPORT Die( void );
virtual int ObjectCaps( void ) { return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } virtual int ObjectCaps( void ) { return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION); }
inline BOOL Explodable( void ) { return ExplosionMagnitude() > 0; } inline BOOL Explodable( void ) { return ExplosionMagnitude() > 0; }
inline int ExplosionMagnitude( void ) { return pev->impulse; } inline int ExplosionMagnitude( void ) { return pev->impulse; }
inline void ExplosionSetMagnitude( int magnitude ) { pev->impulse = magnitude; } inline void ExplosionSetMagnitude( int magnitude ) { pev->impulse = magnitude; }
static void MaterialSoundPrecache( Materials precacheMaterial ); static void MaterialSoundPrecache( Materials precacheMaterial );
static void MaterialSoundRandom( edict_t *pEdict, Materials soundMaterial, float volume ); static void MaterialSoundRandom( edict_t *pEdict, Materials soundMaterial, float volume );
static const char **MaterialSoundList( Materials precacheMaterial, int &soundCount ); static const char **MaterialSoundList( Materials precacheMaterial, int &soundCount );
static const char *pSoundsWood[]; static const char *pSoundsWood[];
static const char *pSoundsFlesh[]; static const char *pSoundsFlesh[];
static const char *pSoundsGlass[]; static const char *pSoundsGlass[];
static const char *pSoundsMetal[]; static const char *pSoundsMetal[];
static const char *pSoundsConcrete[]; static const char *pSoundsConcrete[];
static const char *pSpawnObjects[]; static const char *pSpawnObjects[];
Materials m_Material; Materials m_Material;
Explosions m_Explosion; Explosions m_Explosion;
int m_idShard; int m_idShard;
float m_angle; float m_angle;
int m_iszGibModel; int m_iszGibModel;
int m_iszSpawnObject; int m_iszSpawnObject;
}; };
#endif // FUNC_BREAK_H #endif // FUNC_BREAK_H

3062
src/dlls/gargantua.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,466 +1,478 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
/* /*
===== generic grenade.cpp ======================================================== ===== generic grenade.cpp ========================================================
*/ */
#include "extdll.h" #include "extdll.h"
#include "util.h" #include "util.h"
#include "cmbase.h" #include "cmbase.h"
#include "cmbasemonster.h" #include "cmbasemonster.h"
#include "monsters.h" #include "monsters.h"
#include "weapons.h" #include "weapons.h"
#include "nodes.h" #include "nodes.h"
#include "decals.h" #include "decals.h"
#include "explode.h" #include "explode.h"
//===================grenade //===================grenade
// Grenades flagged with this will be triggered when the owner calls detonateSatchelCharges // Grenades flagged with this will be triggered when the owner calls detonateSatchelCharges
#define SF_DETONATE 0x0001 #define SF_DETONATE 0x0001
// //
// Grenade Explode // Grenade Explode
// //
void CMGrenade::Explode( Vector vecSrc, Vector vecAim ) void CMGrenade::Explode( Vector vecSrc, Vector vecAim )
{ {
TraceResult tr; TraceResult tr;
UTIL_TraceLine ( pev->origin, pev->origin + Vector ( 0, 0, -32 ), ignore_monsters, ENT(pev), & tr); UTIL_TraceLine ( pev->origin, pev->origin + Vector ( 0, 0, -32 ), ignore_monsters, ENT(pev), & tr);
Explode( &tr, DMG_BLAST ); Explode( &tr, DMG_BLAST );
} }
// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution. // UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution.
void CMGrenade::Explode( TraceResult *pTrace, int bitsDamageType ) void CMGrenade::Explode( TraceResult *pTrace, int bitsDamageType )
{ {
float flRndSound;// sound randomizer // CRITICAL - always ensure owner of grenade is valid
if (m_hOwner == NULL)
pev->model = iStringNull;//invisible pev->owner = NULL;
pev->solid = SOLID_NOT;// intangible
float flRndSound;// sound randomizer
pev->takedamage = DAMAGE_NO;
pev->model = iStringNull;//invisible
// Pull out of the wall a bit pev->solid = SOLID_NOT;// intangible
if ( pTrace->flFraction != 1.0 )
{ pev->takedamage = DAMAGE_NO;
pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * (pev->dmg - 24) * 0.6);
} // Pull out of the wall a bit
if ( pTrace->flFraction != 1.0 )
int iContents = UTIL_PointContents ( pev->origin ); {
pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * (pev->dmg - 24) * 0.6);
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin ); }
WRITE_BYTE( TE_EXPLOSION ); // This makes a dynamic light and the explosion sprites/sound
WRITE_COORD( pev->origin.x ); // Send to PAS because of the sound int iContents = UTIL_PointContents ( pev->origin );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z ); MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
if (iContents != CONTENTS_WATER) WRITE_BYTE( TE_EXPLOSION ); // This makes a dynamic light and the explosion sprites/sound
{ WRITE_COORD( pev->origin.x ); // Send to PAS because of the sound
WRITE_SHORT( g_sModelIndexFireball ); WRITE_COORD( pev->origin.y );
} WRITE_COORD( pev->origin.z );
else if (iContents != CONTENTS_WATER)
{ {
WRITE_SHORT( g_sModelIndexWExplosion ); WRITE_SHORT( g_sModelIndexFireball );
} }
WRITE_BYTE( (pev->dmg - 50) * .60 ); // scale * 10 else
WRITE_BYTE( 15 ); // framerate {
WRITE_BYTE( TE_EXPLFLAG_NONE ); WRITE_SHORT( g_sModelIndexWExplosion );
MESSAGE_END(); }
WRITE_BYTE( (pev->dmg - 50) * .60 ); // scale * 10
entvars_t *pevOwner; WRITE_BYTE( 15 ); // framerate
if ( pev->owner ) WRITE_BYTE( TE_EXPLFLAG_NONE );
pevOwner = VARS( pev->owner ); MESSAGE_END();
else
pevOwner = NULL; entvars_t *pevOwner;
if ( pev->owner )
pev->owner = NULL; // can't traceline attack owner if this is set pevOwner = VARS( pev->owner );
else
RadiusDamage ( pev, pevOwner, pev->dmg, CLASS_NONE, bitsDamageType ); pevOwner = NULL;
if ( RANDOM_FLOAT( 0 , 1 ) < 0.5 ) pev->owner = NULL; // can't traceline attack owner if this is set
{
UTIL_DecalTrace( pTrace, DECAL_SCORCH1 ); RadiusDamage ( pev, pevOwner, pev->dmg, CLASS_NONE, bitsDamageType );
}
else if ( RANDOM_FLOAT( 0 , 1 ) < 0.5 )
{ {
UTIL_DecalTrace( pTrace, DECAL_SCORCH2 ); UTIL_DecalTrace( pTrace, DECAL_SCORCH1 );
} }
else
flRndSound = RANDOM_FLOAT( 0 , 1 ); {
UTIL_DecalTrace( pTrace, DECAL_SCORCH2 );
switch ( RANDOM_LONG( 0, 2 ) ) }
{
case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM); break; flRndSound = RANDOM_FLOAT( 0 , 1 );
case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM); break;
case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM); break; switch ( RANDOM_LONG( 0, 2 ) )
} {
case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM); break;
pev->effects |= EF_NODRAW; case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM); break;
SetThink( &CMGrenade::Smoke ); case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM); break;
pev->velocity = g_vecZero; }
pev->nextthink = gpGlobals->time + 0.3;
pev->effects |= EF_NODRAW;
/*jlb SetThink( &CMGrenade::Smoke );
if (iContents != CONTENTS_WATER) pev->velocity = g_vecZero;
{ pev->nextthink = gpGlobals->time + 0.3;
int sparkCount = RANDOM_LONG(0,3);
for ( int i = 0; i < sparkCount; i++ ) /*jlb
Create( "spark_shower", pev->origin, pTrace->vecPlaneNormal, NULL ); if (iContents != CONTENTS_WATER)
} {
jlb*/ int sparkCount = RANDOM_LONG(0,3);
} for ( int i = 0; i < sparkCount; i++ )
Create( "spark_shower", pev->origin, pTrace->vecPlaneNormal, NULL );
}
void CMGrenade::Smoke( void ) jlb*/
{ }
if (UTIL_PointContents ( pev->origin ) == CONTENTS_WATER)
{
UTIL_Bubbles( pev->origin - Vector( 64, 64, 64 ), pev->origin + Vector( 64, 64, 64 ), 100 ); void CMGrenade::Smoke( void )
} {
else if (UTIL_PointContents ( pev->origin ) == CONTENTS_WATER)
{ {
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin ); UTIL_Bubbles( pev->origin - Vector( 64, 64, 64 ), pev->origin + Vector( 64, 64, 64 ), 100 );
WRITE_BYTE( TE_SMOKE ); }
WRITE_COORD( pev->origin.x ); else
WRITE_COORD( pev->origin.y ); {
WRITE_COORD( pev->origin.z ); MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
WRITE_SHORT( g_sModelIndexSmoke ); WRITE_BYTE( TE_SMOKE );
WRITE_BYTE( (pev->dmg - 50) * 0.80 ); // scale * 10 WRITE_COORD( pev->origin.x );
WRITE_BYTE( 12 ); // framerate WRITE_COORD( pev->origin.y );
MESSAGE_END(); WRITE_COORD( pev->origin.z );
} WRITE_SHORT( g_sModelIndexSmoke );
UTIL_Remove( this->edict() ); WRITE_BYTE( (pev->dmg - 50) * 0.80 ); // scale * 10
} WRITE_BYTE( 12 ); // framerate
MESSAGE_END();
void CMGrenade::Killed( entvars_t *pevAttacker, int iGib ) }
{ UTIL_Remove( this->edict() );
Detonate( ); }
}
void CMGrenade::Killed( entvars_t *pevAttacker, int iGib )
{
// Timed grenade, this think is called when time runs out. Detonate( );
void CMGrenade::DetonateUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value ) }
{
SetThink( &CMGrenade::Detonate );
pev->nextthink = gpGlobals->time; // Timed grenade, this think is called when time runs out.
} void CMGrenade::DetonateUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
{
void CMGrenade::PreDetonate( void ) SetThink( &CMGrenade::Detonate );
{ pev->nextthink = gpGlobals->time;
SetThink( &CMGrenade::Detonate ); }
pev->nextthink = gpGlobals->time + 1;
} void CMGrenade::PreDetonate( void )
{
SetThink( &CMGrenade::Detonate );
void CMGrenade::Detonate( void ) pev->nextthink = gpGlobals->time + 1;
{ }
TraceResult tr;
Vector vecSpot;// trace starts here!
void CMGrenade::Detonate( void )
vecSpot = pev->origin + Vector ( 0 , 0 , 8 ); {
UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -40 ), ignore_monsters, ENT(pev), & tr); TraceResult tr;
Vector vecSpot;// trace starts here!
Explode( &tr, DMG_BLAST );
} vecSpot = pev->origin + Vector ( 0 , 0 , 8 );
UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -40 ), ignore_monsters, ENT(pev), & tr);
// Explode( &tr, DMG_BLAST );
// Contact grenade, explode when it touches something }
//
void CMGrenade::ExplodeTouch( edict_t *pOther )
{ //
TraceResult tr; // Contact grenade, explode when it touches something
Vector vecSpot;// trace starts here! //
void CMGrenade::ExplodeTouch( edict_t *pOther )
pev->enemy = pOther; {
TraceResult tr;
vecSpot = pev->origin - pev->velocity.Normalize() * 32; Vector vecSpot;// trace starts here!
UTIL_TraceLine( vecSpot, vecSpot + pev->velocity.Normalize() * 64, ignore_monsters, ENT(pev), &tr );
pev->enemy = pOther;
Explode( &tr, DMG_BLAST );
} vecSpot = pev->origin - pev->velocity.Normalize() * 32;
UTIL_TraceLine( vecSpot, vecSpot + pev->velocity.Normalize() * 64, ignore_monsters, ENT(pev), &tr );
void CMGrenade::DangerSoundThink( void ) Explode( &tr, DMG_BLAST );
{ }
if (!IsInWorld())
{
UTIL_Remove( this->edict() ); void CMGrenade::DangerSoundThink( void )
return; {
} if (!IsInWorld())
{
pev->nextthink = gpGlobals->time + 0.2; UTIL_Remove( this->edict() );
return;
if (pev->waterlevel != 0) }
{
pev->velocity = pev->velocity * 0.5; pev->nextthink = gpGlobals->time + 0.2;
}
} if (pev->waterlevel != 0)
{
pev->velocity = pev->velocity * 0.5;
void CMGrenade::BounceTouch( edict_t *pOther ) }
{ }
// don't hit the guy that launched this grenade
if ( pOther == pev->owner )
return; void CMGrenade::BounceTouch( edict_t *pOther )
{
// only do damage if we're moving fairly fast // don't hit the guy that launched this grenade
if (m_flNextAttack < gpGlobals->time && pev->velocity.Length() > 100) if ( pOther == pev->owner )
{ return;
entvars_t *pevOwner = VARS( pev->owner );
if (pevOwner) // only do damage if we're moving fairly fast
{ if (m_flNextAttack < gpGlobals->time && pev->velocity.Length() > 100)
TraceResult tr = UTIL_GetGlobalTrace( ); {
ClearMultiDamage( ); entvars_t *pevOwner = VARS( pev->owner );
if (pevOwner)
if (UTIL_IsPlayer(pOther)) {
UTIL_TraceAttack(pOther, pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB ); TraceResult tr = UTIL_GetGlobalTrace( );
else if (pOther->v.euser4 != NULL) ClearMultiDamage( );
{
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther)); if (UTIL_IsPlayer(pOther))
pMonster->TraceAttack(pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB ); UTIL_TraceAttack(pOther, pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB );
} else if (pOther->v.euser4 != NULL)
{
ApplyMultiDamage( pev, pevOwner); CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
} pMonster->TraceAttack(pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB );
m_flNextAttack = gpGlobals->time + 1.0; // debounce }
} else
UTIL_TraceAttack(pOther, pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB); // lmao
Vector vecTestVelocity;
// pev->avelocity = Vector (300, 300, 300); ApplyMultiDamage( pev, pevOwner);
}
// this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical m_flNextAttack = gpGlobals->time + 1.0; // debounce
// or thrown very far tend to slow down too quickly for me to always catch just by testing velocity. }
// trimming the Z velocity a bit seems to help quite a bit.
vecTestVelocity = pev->velocity; Vector vecTestVelocity;
vecTestVelocity.z *= 0.45; // pev->avelocity = Vector (300, 300, 300);
if ( !m_fRegisteredSound && vecTestVelocity.Length() <= 60 ) // this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical
{ // or thrown very far tend to slow down too quickly for me to always catch just by testing velocity.
//ALERT( at_console, "Grenade Registered!: %f\n", vecTestVelocity.Length() ); // trimming the Z velocity a bit seems to help quite a bit.
vecTestVelocity = pev->velocity;
// grenade is moving really slow. It's probably very close to where it will ultimately stop moving. vecTestVelocity.z *= 0.45;
// go ahead and emit the danger sound.
if ( !m_fRegisteredSound && vecTestVelocity.Length() <= 60 )
// register a radius louder than the explosion, so we make sure everyone gets out of the way {
m_fRegisteredSound = TRUE; //ALERT( at_console, "Grenade Registered!: %f\n", vecTestVelocity.Length() );
}
// grenade is moving really slow. It's probably very close to where it will ultimately stop moving.
if (pev->flags & FL_ONGROUND) // go ahead and emit the danger sound.
{
// add a bit of static friction // register a radius louder than the explosion, so we make sure everyone gets out of the way
pev->velocity = pev->velocity * 0.8; m_fRegisteredSound = TRUE;
}
pev->sequence = RANDOM_LONG( 1, 1 );
} if (pev->flags & FL_ONGROUND)
else {
{ // add a bit of static friction
// play bounce sound pev->velocity = pev->velocity * 0.8;
BounceSound();
} pev->sequence = RANDOM_LONG( 1, 1 );
pev->framerate = pev->velocity.Length() / 200.0; }
if (pev->framerate > 1.0) else
pev->framerate = 1; {
else if (pev->framerate < 0.5) // play bounce sound
pev->framerate = 0; BounceSound();
}
} pev->framerate = pev->velocity.Length() / 200.0;
if (pev->framerate > 1.0)
pev->framerate = 1;
else if (pev->framerate < 0.5)
void CMGrenade::SlideTouch( edict_t *pOther ) pev->framerate = 0;
{ }
// don't hit the guy that launched this grenade
if ( pOther == pev->owner )
return;
void CMGrenade::SlideTouch( edict_t *pOther )
// pev->avelocity = Vector (300, 300, 300); {
// don't hit the guy that launched this grenade
if (pev->flags & FL_ONGROUND) if ( pOther == pev->owner )
{ return;
// add a bit of static friction
pev->velocity = pev->velocity * 0.95; // pev->avelocity = Vector (300, 300, 300);
if (pev->velocity.x != 0 || pev->velocity.y != 0) if (pev->flags & FL_ONGROUND)
{ {
// maintain sliding sound // add a bit of static friction
} pev->velocity = pev->velocity * 0.95;
}
else if (pev->velocity.x != 0 || pev->velocity.y != 0)
{ {
BounceSound(); // maintain sliding sound
} }
} }
else
void CMGrenade :: BounceSound( void ) {
{ BounceSound();
switch ( RANDOM_LONG( 0, 2 ) ) }
{ }
case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/grenade_hit1.wav", 0.25, ATTN_NORM); break;
case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/grenade_hit2.wav", 0.25, ATTN_NORM); break; void CMGrenade :: BounceSound( void )
case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/grenade_hit3.wav", 0.25, ATTN_NORM); break; {
} // CRITICAL - always ensure owner of grenade is valid
} if (m_hOwner == NULL)
pev->owner = NULL;
void CMGrenade :: TumbleThink( void )
{ switch ( RANDOM_LONG( 0, 2 ) )
if (!IsInWorld()) {
{ case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/grenade_hit1.wav", 0.25, ATTN_NORM); break;
UTIL_Remove( this->edict() ); case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/grenade_hit2.wav", 0.25, ATTN_NORM); break;
return; case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/grenade_hit3.wav", 0.25, ATTN_NORM); break;
} }
}
StudioFrameAdvance( );
pev->nextthink = gpGlobals->time + 0.1; void CMGrenade :: TumbleThink( void )
{
if (pev->dmgtime <= gpGlobals->time) if (!IsInWorld())
{ {
SetThink( &CMGrenade::Detonate ); UTIL_Remove( this->edict() );
} return;
if (pev->waterlevel != 0) }
{
pev->velocity = pev->velocity * 0.5; StudioFrameAdvance( );
pev->framerate = 0.2; pev->nextthink = gpGlobals->time + 0.1;
}
} if (pev->dmgtime <= gpGlobals->time)
{
SetThink( &CMGrenade::Detonate );
void CMGrenade:: Spawn( void ) }
{ if (pev->waterlevel != 0)
pev->movetype = MOVETYPE_BOUNCE; {
pev->classname = MAKE_STRING( "grenade" ); pev->velocity = pev->velocity * 0.5;
pev->framerate = 0.2;
pev->solid = SOLID_BBOX; }
}
SET_MODEL(ENT(pev), "models/grenade.mdl");
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
void CMGrenade:: Spawn( void )
pev->dmg = 100; {
m_fRegisteredSound = FALSE; pev->movetype = MOVETYPE_BOUNCE;
} pev->classname = MAKE_STRING( "grenade" );
pev->solid = SOLID_BBOX;
CMGrenade *CMGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
{ SET_MODEL(ENT(pev), "models/grenade.mdl");
CMGrenade *pGrenade = CreateClassPtr( (CMGrenade *)NULL ); UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
if (pGrenade == NULL) // no free monster edicts left? pev->dmg = 100;
return NULL; m_fRegisteredSound = FALSE;
}
pGrenade->Spawn();
// contact grenades arc lower
pGrenade->pev->gravity = 0.5;// lower gravity since grenade is aerodynamic and engine doesn't know it. CMGrenade *CMGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
UTIL_SetOrigin( pGrenade->pev, vecStart ); {
pGrenade->pev->velocity = vecVelocity; CMGrenade *pGrenade = CreateClassPtr( (CMGrenade *)NULL );
pGrenade->pev->angles = UTIL_VecToAngles (pGrenade->pev->velocity);
pGrenade->pev->owner = ENT(pevOwner); if (pGrenade == NULL) // no free monster edicts left?
return NULL;
// make monsters afaid of it while in the air
pGrenade->SetThink( &CMGrenade::DangerSoundThink ); pGrenade->Spawn();
pGrenade->pev->nextthink = gpGlobals->time; // contact grenades arc lower
pGrenade->pev->gravity = 0.5;// lower gravity since grenade is aerodynamic and engine doesn't know it.
// Tumble in air UTIL_SetOrigin( pGrenade->pev, vecStart );
pGrenade->pev->avelocity.x = RANDOM_FLOAT ( -100, -500 ); pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles (pGrenade->pev->velocity);
// Explode on contact pGrenade->pev->owner = ENT(pevOwner);
pGrenade->SetTouch( &CMGrenade::ExplodeTouch ); pGrenade->m_hOwner = ENT(pevOwner);
pGrenade->pev->dmg = gSkillData.monDmgM203Grenade; // make monsters afaid of it while in the air
pGrenade->SetThink( &CMGrenade::DangerSoundThink );
return pGrenade; pGrenade->pev->nextthink = gpGlobals->time;
}
// Tumble in air
pGrenade->pev->avelocity.x = RANDOM_FLOAT ( -100, -500 );
CMGrenade * CMGrenade:: ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time )
{ // Explode on contact
CMGrenade *pGrenade = CreateClassPtr( (CMGrenade *)NULL ); pGrenade->SetTouch( &CMGrenade::ExplodeTouch );
if (pGrenade == NULL) // no free monster edicts left? pGrenade->pev->dmg = gSkillData.monDmgM203Grenade;
return NULL;
return pGrenade;
pGrenade->Spawn(); }
UTIL_SetOrigin( pGrenade->pev, vecStart );
pGrenade->pev->velocity = vecVelocity;
pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity); CMGrenade * CMGrenade:: ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time )
pGrenade->pev->owner = ENT(pevOwner); {
CMGrenade *pGrenade = CreateClassPtr( (CMGrenade *)NULL );
pGrenade->SetTouch( &CMGrenade::BounceTouch ); // Bounce if touched
if (pGrenade == NULL) // no free monster edicts left?
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate return NULL;
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
// the grenade explodes after the exact amount of time specified in the call to ShootTimed(). pGrenade->Spawn();
UTIL_SetOrigin( pGrenade->pev, vecStart );
pGrenade->pev->dmgtime = gpGlobals->time + time; pGrenade->pev->velocity = vecVelocity;
pGrenade->SetThink( &CMGrenade::TumbleThink ); pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity);
pGrenade->pev->nextthink = gpGlobals->time + 0.1; pGrenade->pev->owner = ENT(pevOwner);
if (time < 0.1) pGrenade->m_hOwner = ENT(pevOwner);
{
pGrenade->pev->nextthink = gpGlobals->time; pGrenade->SetTouch( &CMGrenade::BounceTouch ); // Bounce if touched
pGrenade->pev->velocity = Vector( 0, 0, 0 );
} // Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
pGrenade->pev->sequence = RANDOM_LONG( 3, 6 ); // the grenade explodes after the exact amount of time specified in the call to ShootTimed().
pGrenade->pev->framerate = 1.0;
pGrenade->pev->dmgtime = gpGlobals->time + time;
// Tumble through the air pGrenade->SetThink( &CMGrenade::TumbleThink );
// pGrenade->pev->avelocity.x = -400; pGrenade->pev->nextthink = gpGlobals->time + 0.1;
if (time < 0.1)
pGrenade->pev->gravity = 0.5; {
pGrenade->pev->friction = 0.8; pGrenade->pev->nextthink = gpGlobals->time;
pGrenade->pev->velocity = Vector( 0, 0, 0 );
SET_MODEL(ENT(pGrenade->pev), "models/w_grenade.mdl"); }
pGrenade->pev->dmg = 100;
pGrenade->pev->sequence = RANDOM_LONG( 3, 6 );
return pGrenade; pGrenade->pev->framerate = 1.0;
}
// Tumble through the air
// pGrenade->pev->avelocity.x = -400;
CMGrenade * CMGrenade :: ShootSatchelCharge( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
{ pGrenade->pev->gravity = 0.5;
CMGrenade *pGrenade = CreateClassPtr( (CMGrenade *)NULL ); pGrenade->pev->friction = 0.8;
if (pGrenade == NULL) // no free monster edicts left? SET_MODEL(ENT(pGrenade->pev), "models/w_grenade.mdl");
return NULL; pGrenade->pev->dmg = 100;
pGrenade->pev->movetype = MOVETYPE_BOUNCE; return pGrenade;
pGrenade->pev->classname = MAKE_STRING( "grenade" ); }
pGrenade->pev->solid = SOLID_BBOX;
CMGrenade * CMGrenade :: ShootSatchelCharge( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
SET_MODEL(ENT(pGrenade->pev), "models/grenade.mdl"); // Change this to satchel charge model {
CMGrenade *pGrenade = CreateClassPtr( (CMGrenade *)NULL );
UTIL_SetSize(pGrenade->pev, Vector( 0, 0, 0), Vector(0, 0, 0));
if (pGrenade == NULL) // no free monster edicts left?
pGrenade->pev->dmg = 200; return NULL;
UTIL_SetOrigin( pGrenade->pev, vecStart );
pGrenade->pev->velocity = vecVelocity; pGrenade->pev->movetype = MOVETYPE_BOUNCE;
pGrenade->pev->angles = g_vecZero; pGrenade->pev->classname = MAKE_STRING( "grenade" );
pGrenade->pev->owner = ENT(pevOwner);
pGrenade->pev->solid = SOLID_BBOX;
// Detonate in "time" seconds
pGrenade->SetThink( &CMGrenade::SUB_DoNothing ); SET_MODEL(ENT(pGrenade->pev), "models/grenade.mdl"); // Change this to satchel charge model
pGrenade->SetUse( &CMGrenade::DetonateUse );
pGrenade->SetTouch( &CMGrenade::SlideTouch ); UTIL_SetSize(pGrenade->pev, Vector( 0, 0, 0), Vector(0, 0, 0));
pGrenade->pev->spawnflags = SF_DETONATE;
pGrenade->pev->dmg = 200;
pGrenade->pev->friction = 0.9; UTIL_SetOrigin( pGrenade->pev, vecStart );
pGrenade->pev->velocity = vecVelocity;
return pGrenade; pGrenade->pev->angles = g_vecZero;
} pGrenade->pev->owner = ENT(pevOwner);
pGrenade->m_hOwner = ENT(pevOwner);
//======================end grenade
// Detonate in "time" seconds
pGrenade->SetThink( &CMGrenade::SUB_DoNothing );
pGrenade->SetUse( &CMGrenade::DetonateUse );
pGrenade->SetTouch( &CMGrenade::SlideTouch );
pGrenade->pev->spawnflags = SF_DETONATE;
pGrenade->pev->friction = 0.9;
return pGrenade;
}
//======================end grenade

170
src/dlls/globalreplace.cpp Normal file
View File

@@ -0,0 +1,170 @@
//=========================================================
// Global Replacement:
// Tool to replace all default models/sounds with a
// customized list.
//=========================================================
#include "extdll.h"
#include "dllapi.h"
#include "meta_api.h"
#include "cmbase.h"
#include "cmbasemonster.h"
namespace REPLACER
{
REPLACER *GMR;
REPLACER *GSR;
int numModels;
int numSounds;
void Init(void)
{
if ( GMR != NULL )
{
free( GMR );
GMR = NULL;
}
if ( GSR != NULL )
{
free( GSR );
GSR = NULL;
}
numModels = 0;
numSounds = 0;
}
bool AddGlobalModel(const char *from, const char *to)
{
if (numModels < MAX_REPLACEMENTS)
{
// allocate for the first time
if (!numModels)
GMR = (REPLACER*)calloc(MAX_REPLACEMENTS, sizeof(*GMR));
strcpy(GMR[numModels].source, from);
strcpy(GMR[numModels].destination, to);
numModels++;
return true;
}
LOG_MESSAGE(PLID, "Can't replace model '%s', too many models in GMR.", from);
return false;
}
bool AddGlobalSound(const char *from, const char *to)
{
if (numSounds < MAX_REPLACEMENTS)
{
if (from[0] == '!')
{
// sentence sounds cannot be replaced, skip.
return false;
}
// allocate for the first time
if (!numSounds)
GSR = (REPLACER*)calloc(MAX_REPLACEMENTS, sizeof(*GSR));
strcpy(GSR[numSounds].source, from);
strcpy(GSR[numSounds].destination, to);
numSounds++;
return true;
}
LOG_MESSAGE(PLID, "Can't replace sound '%s', too many sounds in GSR.", from);
return false;
}
bool AddIndividualSound(edict_t *pMonster, const char *from, const char *to)
{
CMBaseMonster *castMonster = GetClassPtr((CMBaseMonster *)VARS(pMonster));
if ( castMonster == NULL )
return false;
int m_iSounds = castMonster->m_isrSounds;
if (m_iSounds < MAX_REPLACEMENTS)
{
// allocate for the first time
if (!m_iSounds)
castMonster->m_srSoundList = (REPLACER*)calloc(MAX_REPLACEMENTS, sizeof(*castMonster->m_srSoundList));
strcpy(castMonster->m_srSoundList[m_iSounds].source, from);
strcpy(castMonster->m_srSoundList[m_iSounds].destination, to);
castMonster->m_isrSounds++;
return true;
}
LOG_MESSAGE(PLID, "Can't replace sound '%s', too many sounds in list.", from);
return false;
}
const char* FindModelReplacement( edict_t *pMonster, const char *from )
{
// Individually set models takes priority!
if (UTIL_IsValidEntity(pMonster) && !FStringNull(pMonster->v.model))
return STRING(pMonster->v.model);
// Find the model
for (int model = 0; model < numModels; model++)
{
if (strcmp(GMR[model].source, from) == 0)
{
// If found, use that model instead
return GMR[model].destination;
}
}
// Nothing found, stick with default
return from;
}
const char* FindSoundReplacement( edict_t *pMonster, const char *from )
{
// Individually set sounds takes priority!
if (UTIL_IsValidEntity(pMonster))
{
CMBaseMonster *castMonster = NULL;
// Check if this is really a monster or not
if (pMonster->v.flags & FL_MONSTER)
castMonster = GetClassPtr((CMBaseMonster *)VARS(pMonster));
else
{
// This is probably a monster-owned projectile of sorts
if (UTIL_IsValidEntity(pMonster->v.owner))
castMonster = GetClassPtr((CMBaseMonster *)VARS(pMonster->v.owner));
}
// If still no valid BaseMonster pointer, full stop, use GSR.
if (castMonster != NULL && castMonster->m_srSoundList != NULL && castMonster->m_isrSounds > 0)
{
for (int sound = 0; sound < castMonster->m_isrSounds; sound++)
{
if (strcmp(castMonster->m_srSoundList[sound].source, from) == 0)
{
// If found, use it
return castMonster->m_srSoundList[sound].destination;
}
}
// If nothing is found stick to GSR if available
}
}
for (int sound = 0; sound < numSounds; sound++)
{
if (strcmp(GSR[sound].source, from) == 0)
{
// If found, use that sound instead
return GSR[sound].destination;
}
}
// Nothing found, stick with default
return from;
}
}

26
src/dlls/globalreplace.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef GLOBALREPLACE_H
#define GLOBALREPLACE_H
#define MAX_REPLACEMENTS 255
namespace REPLACER
{
typedef struct
{
char source[128];
char destination[128];
} REPLACER;
void Init(void);
bool AddGlobalModel(const char *from, const char *to);
bool AddGlobalSound(const char *from, const char *to);
bool AddIndividualSound(edict_t *pMonster, const char *from, const char *to);
const char* FindModelReplacement( edict_t *pMonster, const char *from );
inline const char* FindModelReplacement( const char *from ) { return FindModelReplacement( NULL, from ); }
const char* FindSoundReplacement( edict_t *pMonster, const char *from );
inline const char* FindSoundReplacement( const char *from ) { return FindSoundReplacement( NULL, from ); }
}
#endif

873
src/dlls/gonome.cpp Normal file
View File

@@ -0,0 +1,873 @@
// HUGE thanks to DrBeef for his hlsdk-xash3d-opfor repository!
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
//=========================================================
// Gonome.cpp
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "animation.h"
#include "decals.h"
#include "nodes.h"
#define GONOME_MELEE_ATTACK_RADIUS 70
enum
{
TASK_GONOME_GET_PATH_TO_ENEMY_CORPSE = LAST_COMMON_TASK + 1
};
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define GONOME_AE_SLASH_RIGHT ( 1 )
#define GONOME_AE_SLASH_LEFT ( 2 )
#define GONOME_AE_SPIT ( 3 )
#define GONOME_AE_THROW ( 4 )
#define GONOME_AE_BITE1 ( 19 )
#define GONOME_AE_BITE2 ( 20 )
#define GONOME_AE_BITE3 ( 21 )
#define GONOME_AE_BITE4 ( 22 )
#define GONOME_SCRIPT_EVENT_SOUND ( 1011 )
void CGonomeGuts :: Spawn( void )
{
pev->movetype = MOVETYPE_FLY;
pev->classname = MAKE_STRING( "gonomeguts" );
pev->solid = SOLID_BBOX;
pev->rendermode = kRenderTransAlpha;
pev->renderamt = 255;
SET_MODEL( ENT( pev ), "sprites/bigspit.spr" );
pev->frame = 0;
pev->scale = 0.5;
pev->rendercolor.x = 255;
UTIL_SetSize( pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) );
m_maxFrame = (float)MODEL_FRAMES( pev->modelindex ) - 1;
}
void CGonomeGuts :: Animate( void )
{
pev->nextthink = gpGlobals->time + 0.1;
if ( pev->frame++ )
{
if ( pev->frame > m_maxFrame )
{
pev->frame = 0;
}
}
}
edict_t *CGonomeGuts :: Shoot( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
{
CGonomeGuts *pSpit = CreateClassPtr( (CGonomeGuts *)NULL );
if (pSpit == NULL)
return NULL;
pSpit->Spawn();
UTIL_SetOrigin( pSpit->pev, vecStart );
pSpit->pev->velocity = vecVelocity;
pSpit->pev->owner = ENT(pevOwner);
pSpit->SetThink ( &CGonomeGuts::Animate );
pSpit->pev->nextthink = gpGlobals->time + 0.1;
pSpit->SetTouch ( &CGonomeGuts::GutsTouch );
return pSpit->edict();
}
void CGonomeGuts :: GutsTouch( edict_t *pOther )
{
TraceResult tr;
int iPitch;
// splat sound
iPitch = RANDOM_FLOAT( 90, 110 );
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, "bullchicken/bc_acid1.wav", 1, ATTN_NORM, 0, iPitch );
switch( RANDOM_LONG( 0, 1 ) )
{
case 0:
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "bullchicken/bc_spithit1.wav", 1, ATTN_NORM, 0, iPitch );
break;
case 1:
EMIT_SOUND_DYN( ENT( pev ), CHAN_WEAPON, "bullchicken/bc_spithit2.wav", 1, ATTN_NORM, 0, iPitch );
break;
}
if( !pOther->v.takedamage )
{
// make a splat on the wall
UTIL_TraceLine( pev->origin, pev->origin + pev->velocity * 10, dont_ignore_monsters, ENT( pev ), &tr );
UTIL_BloodDecalTrace( &tr, BLOOD_COLOR_RED );
UTIL_BloodDrips( tr.vecEndPos, UTIL_RandomBloodVector(), BLOOD_COLOR_RED, 35 );
}
else
{
if (UTIL_IsPlayer(pOther))
UTIL_TakeDamage( pOther, pev, VARS(pev->owner), gSkillData.gonomeDmgGuts, DMG_GENERIC );
else if (pOther->v.euser4 != NULL)
{
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
pMonster->TakeDamage ( pev, VARS(pev->owner), gSkillData.gonomeDmgGuts, DMG_GENERIC );
}
else
UTIL_TakeDamageExternal( pOther, pev, VARS(pev->owner), gSkillData.gonomeDmgGuts, DMG_GENERIC );
}
SetThink( &CGonomeGuts::SUB_Remove );
pev->nextthink = gpGlobals->time;
}
const char* CMGonome::pPainSounds[] = {
"gonome/gonome_pain1.wav",
"gonome/gonome_pain2.wav",
"gonome/gonome_pain3.wav",
"gonome/gonome_pain4.wav"
};
const char* CMGonome::pIdleSounds[] = {
"gonome/gonome_idle1.wav",
"gonome/gonome_idle2.wav",
"gonome/gonome_idle3.wav"
};
const char* CMGonome::pDeathSounds[] = {
"gonome/gonome_death2.wav",
"gonome/gonome_death3.wav",
"gonome/gonome_death4.wav"
};
const char* CMGonome::pAttackHitSounds[] =
{
"zombie/claw_strike1.wav",
"zombie/claw_strike2.wav",
"zombie/claw_strike3.wav",
};
const char* CMGonome::pAttackMissSounds[] =
{
"zombie/claw_miss1.wav",
"zombie/claw_miss2.wav",
};
void CMGonome::Killed(entvars_t *pevAttacker, int iGib)
{
ClearGuts();
UnlockPlayer();
CMBaseMonster::Killed(pevAttacker, iGib);
}
void CMGonome::UnlockPlayer()
{
if (m_fPlayerLocked)
{
edict_t *player = 0;
if (m_lockedPlayer != 0 && UTIL_IsPlayer(m_lockedPlayer))
player = m_lockedPlayer;
else // if ehandle is empty for some reason just unlock the first player
player = UTIL_FindEntityByClassname(0, "player");
if (player)
player->v.flags &= ~FL_FROZEN;
m_lockedPlayer = 0;
m_fPlayerLocked = FALSE;
}
}
CGonomeGuts* CMGonome::GetGonomeGuts(entvars_t *pevOwner, const Vector &pos)
{
if (m_pGonomeGuts)
return m_pGonomeGuts;
edict_t *pEdict = CGonomeGuts::Shoot( pevOwner, g_vecZero, g_vecZero );
CGonomeGuts *pGuts = GetClassPtr((CGonomeGuts*)VARS(pEdict));
pGuts->Spawn();
UTIL_SetOrigin( pGuts->pev, pos );
m_pGonomeGuts = pGuts;
return m_pGonomeGuts;
}
void CMGonome::ClearGuts()
{
if (m_pGonomeGuts)
{
UTIL_Remove( m_pGonomeGuts->edict() );
m_pGonomeGuts = 0;
}
}
void CMGonome::PainSound( void )
{
int pitch = 95 + RANDOM_LONG( 0, 9 );
if( RANDOM_LONG( 0, 5 ) < 2 )
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, RANDOM_SOUND_ARRAY(pPainSounds), 1.0, ATTN_NORM, 0, pitch );
}
void CMGonome::DeathSound( void )
{
int pitch = 95 + RANDOM_LONG( 0, 9 );
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, RANDOM_SOUND_ARRAY(pDeathSounds), 1.0, ATTN_NORM, 0, pitch );
}
void CMGonome::IdleSound( void )
{
int pitch = 95 + RANDOM_LONG( 0, 9 );
// Play a random idle sound
EMIT_SOUND_DYN( ENT( pev ), CHAN_VOICE, RANDOM_SOUND_ARRAY(pIdleSounds), 1.0, ATTN_NORM, 0, pitch );
}
void CMGonome::AlertSound( void )
{
const int iPitch = RANDOM_LONG(0, 9) + 95;
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, RANDOM_SOUND_ARRAY(pIdleSounds), 1, ATTN_NORM, 0, iPitch);
}
void CMGonome::SetActivity( Activity NewActivity )
{
Activity OldActivity = m_Activity;
int iSequence = ACTIVITY_NOT_AVAILABLE;
if (NewActivity != ACT_RANGE_ATTACK1)
{
ClearGuts();
}
if (NewActivity == ACT_MELEE_ATTACK1 && m_hEnemy != 0)
{
// special melee animations
if ((pev->origin - m_hEnemy->v.origin).Length2D() >= 48 )
{
m_meleeAttack2 = false;
iSequence = LookupSequence("attack1");
}
else
{
m_meleeAttack2 = true;
iSequence = LookupSequence("attack2");
}
}
else
{
UnlockPlayer();
if (NewActivity == ACT_RUN && m_hEnemy != 0)
{
// special run animations
if ((pev->origin - m_hEnemy->v.origin).Length2D() <= 512 )
{
iSequence = LookupSequence("runshort");
}
else
{
iSequence = LookupSequence("runlong");
}
}
else
{
iSequence = LookupActivity(NewActivity);
}
}
m_Activity = NewActivity; // Go ahead and set this so it doesn't keep trying when the anim is not present
// In case someone calls this with something other than the ideal activity
m_IdealActivity = m_Activity;
// Set to the desired anim, or default anim if the desired is not present
if( iSequence > ACTIVITY_NOT_AVAILABLE )
{
if( pev->sequence != iSequence || !m_fSequenceLoops )
{
// don't reset frame between walk and run
if( !( OldActivity == ACT_WALK || OldActivity == ACT_RUN ) || !( NewActivity == ACT_WALK || NewActivity == ACT_RUN ) )
pev->frame = 0;
}
pev->sequence = iSequence; // Set to the reset anim (if it's there)
ResetSequenceInfo();
SetYawSpeed();
}
else
{
// Not available try to get default anim
ALERT( at_aiconsole, "%s has no sequence for act:%d\n", STRING( pev->classname ), NewActivity );
pev->sequence = 0; // Set to the reset anim (if it's there)
}
}
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CMGonome::Classify(void)
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_ALIEN_MONSTER;
}
//=========================================================
// TakeDamage - overridden for gonome so we can keep track
// of how much time has passed since it was last injured
//=========================================================
int CMGonome::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType)
{
// HACK HACK -- until we fix this.
if( IsAlive() )
PainSound();
return CMBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
}
//=========================================================
// CheckRangeAttack1
//=========================================================
BOOL CMGonome::CheckRangeAttack1(float flDot, float flDist)
{
if (flDist < 256)
return FALSE;
if (IsMoving() && flDist >= 512)
{
// squid will far too far behind if he stops running to spit at this distance from the enemy.
return FALSE;
}
if (flDist > 64 && flDist <= 784 && flDot >= 0.5 && gpGlobals->time >= m_flNextThrowTime)
{
if (m_hEnemy != 0)
{
if (fabs(pev->origin.z - m_hEnemy->v.origin.z) > 256)
{
// don't try to spit at someone up really high or down really low.
return FALSE;
}
}
if (IsMoving())
{
// don't spit again for a long time, resume chasing enemy.
m_flNextThrowTime = gpGlobals->time + 5;
}
else
{
// not moving, so spit again pretty soon.
m_flNextThrowTime = gpGlobals->time + 0.5;
}
return TRUE;
}
return FALSE;
}
//=========================================================
// CheckMeleeAttack2 - both gonome's melee attacks are ACT_MELEE_ATTACK1
//=========================================================
BOOL CMGonome::CheckMeleeAttack2(float flDot, float flDist)
{
return FALSE;
}
//=========================================================
// SetYawSpeed - allows each sequence to have a different
// turn rate associated with it.
//=========================================================
void CMGonome::SetYawSpeed( void )
{
pev->yaw_speed = 120;
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CMGonome::HandleAnimEvent(MonsterEvent_t *pEvent)
{
switch (pEvent->event)
{
case GONOME_SCRIPT_EVENT_SOUND:
if (m_Activity != ACT_MELEE_ATTACK1)
EMIT_SOUND(ENT(pev), CHAN_BODY, pEvent->options, 1, ATTN_NORM);
break;
case GONOME_AE_SPIT:
{
Vector vecArmPos, vecArmAng;
GetAttachment(0, vecArmPos, vecArmAng);
if (GetGonomeGuts(pev, vecArmPos))
{
m_pGonomeGuts->pev->skin = entindex();
m_pGonomeGuts->pev->body = 1;
m_pGonomeGuts->pev->aiment = ENT(pev);
m_pGonomeGuts->pev->movetype = MOVETYPE_FOLLOW;
}
UTIL_BloodDrips( vecArmPos, UTIL_RandomBloodVector(), BLOOD_COLOR_RED, 35 );
}
break;
case GONOME_AE_THROW:
{
UTIL_MakeVectors(pev->angles);
Vector vecArmPos, vecArmAng;
GetAttachment(0, vecArmPos, vecArmAng);
if (GetGonomeGuts(pev, vecArmPos))
{
Vector vecSpitDir;
Vector vecEnemyPosition;
if (m_hEnemy != 0)
vecEnemyPosition = (m_hEnemy->v.origin + m_hEnemy->v.view_ofs);
else
vecEnemyPosition = m_vecEnemyLKP;
vecSpitDir = (vecEnemyPosition - vecArmPos).Normalize();
vecSpitDir.x += RANDOM_FLOAT(-0.05, 0.05);
vecSpitDir.y += RANDOM_FLOAT(-0.05, 0.05);
vecSpitDir.z += RANDOM_FLOAT(-0.05, 0);
m_pGonomeGuts->pev->body = 0;
m_pGonomeGuts->pev->skin = 0;
m_pGonomeGuts->pev->owner = ENT( pev );
m_pGonomeGuts->pev->aiment = 0;
m_pGonomeGuts->pev->movetype = MOVETYPE_FLY;
m_pGonomeGuts->pev->velocity = vecSpitDir * 900;
m_pGonomeGuts->SetThink( &CGonomeGuts::Animate );
m_pGonomeGuts->pev->nextthink = gpGlobals->time + 0.1;
UTIL_SetOrigin(m_pGonomeGuts->pev, vecArmPos);
m_pGonomeGuts = 0;
}
UTIL_BloodDrips( vecArmPos, UTIL_RandomBloodVector(), BLOOD_COLOR_RED, 35 );
}
break;
case GONOME_AE_SLASH_LEFT:
{
edict_t *pHurt = CheckTraceHullAttack(GONOME_MELEE_ATTACK_RADIUS, gSkillData.gonomeDmgOneSlash, DMG_SLASH);
if (pHurt)
{
if (FBitSet(pHurt->v.flags, FL_MONSTER|FL_CLIENT))
{
pHurt->v.punchangle.z = 9;
pHurt->v.punchangle.x = 5;
pHurt->v.velocity = pHurt->v.velocity + gpGlobals->v_right * 25;
}
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackHitSounds), 1, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5));
}
else
{
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackMissSounds), 1, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5));
}
}
break;
case GONOME_AE_SLASH_RIGHT:
{
edict_t *pHurt = CheckTraceHullAttack(GONOME_MELEE_ATTACK_RADIUS, gSkillData.gonomeDmgOneSlash, DMG_SLASH);
if (pHurt)
{
if (FBitSet(pHurt->v.flags, FL_MONSTER|FL_CLIENT))
{
pHurt->v.punchangle.z = -9;
pHurt->v.punchangle.x = 5;
pHurt->v.velocity = pHurt->v.velocity + gpGlobals->v_right * -25;
}
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackHitSounds), 1, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5));
}
else
{
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, RANDOM_SOUND_ARRAY(pAttackMissSounds), 1, ATTN_NORM, 0, 100 + RANDOM_LONG(-5,5));
}
}
break;
case GONOME_AE_BITE1:
case GONOME_AE_BITE2:
case GONOME_AE_BITE3:
case GONOME_AE_BITE4:
{
int iPitch;
edict_t *pHurt = CheckTraceHullAttack(GONOME_MELEE_ATTACK_RADIUS, gSkillData.gonomeDmgOneBite, DMG_SLASH);
if (pHurt)
{
// croonchy bite sound
iPitch = RANDOM_FLOAT(90, 110);
switch (RANDOM_LONG(0, 1))
{
case 0:
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_bite2.wav", 1, ATTN_NORM, 0, iPitch);
break;
case 1:
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "bullchicken/bc_bite3.wav", 1, ATTN_NORM, 0, iPitch);
break;
}
if (FBitSet(pHurt->v.flags, FL_MONSTER|FL_CLIENT))
{
if (pEvent->event == GONOME_AE_BITE4)
{
pHurt->v.punchangle.x = 15;
pHurt->v.velocity = pHurt->v.velocity - gpGlobals->v_forward * 75;
}
else
{
pHurt->v.punchangle.x = 9;
pHurt->v.velocity = pHurt->v.velocity - gpGlobals->v_forward * 25;
}
}
// lock player
if (pEvent->event == GONOME_AE_BITE4)
{
UnlockPlayer();
}
else if (UTIL_IsPlayer( pHurt ) && UTIL_IsAlive( pHurt ))
{
if (!m_fPlayerLocked)
{
edict_t *player = pHurt;
player->v.flags |= FL_FROZEN;
m_lockedPlayer = player;
m_fPlayerLocked = TRUE;
}
}
}
}
break;
default:
CMBaseMonster::HandleAnimEvent(pEvent);
}
}
#define GONOME_FLINCH_DELAY 2
int CMGonome::IgnoreConditions( void )
{
int iIgnore = CMBaseMonster::IgnoreConditions();
if( m_Activity == ACT_MELEE_ATTACK1 )
{
if( m_flNextFlinch >= gpGlobals->time )
iIgnore |= ( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE );
}
if( ( m_Activity == ACT_SMALL_FLINCH ) || ( m_Activity == ACT_BIG_FLINCH ) )
{
if( m_flNextFlinch < gpGlobals->time )
m_flNextFlinch = gpGlobals->time + GONOME_FLINCH_DELAY;
}
return iIgnore;
}
//=========================================================
// Spawn
//=========================================================
void CMGonome::Spawn()
{
Precache();
SET_MODEL(ENT(pev), (!FStringNull( pev->model ) ? STRING( pev->model ) : "models/gonome.mdl"));
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = !m_bloodColor ? BLOOD_COLOR_YELLOW : m_bloodColor;
pev->effects = 0;
if (!pev->health) { pev->health = gSkillData.gonomeHealth; }
m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
m_flNextThrowTime = gpGlobals->time;
MonsterInit();
pev->classname = MAKE_STRING( "monster_gonome" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Gonome" );
}
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CMGonome::Precache()
{
PRECACHE_MODEL("models/gonome.mdl");
PRECACHE_MODEL("sprites/bigspit.spr");// spit projectile.
PRECACHE_SOUND("zombie/claw_miss2.wav");// because we use the basemonster SWIPE animation event
PRECACHE_SOUND("gonome/gonome_eat.wav");
PRECACHE_SOUND("gonome/gonome_jumpattack.wav");
PRECACHE_SOUND("gonome/gonome_melee1.wav");
PRECACHE_SOUND("gonome/gonome_melee2.wav");
PRECACHE_SOUND_ARRAY(pIdleSounds);
PRECACHE_SOUND_ARRAY(pPainSounds);
PRECACHE_SOUND_ARRAY(pDeathSounds);
PRECACHE_SOUND("gonome/gonome_run.wav");
PRECACHE_SOUND("bullchicken/bc_acid1.wav");
PRECACHE_SOUND("bullchicken/bc_bite2.wav");
PRECACHE_SOUND("bullchicken/bc_bite3.wav");
PRECACHE_SOUND("bullchicken/bc_spithit1.wav");
PRECACHE_SOUND("bullchicken/bc_spithit2.wav");
}
//=========================================================
// GetSchedule
//=========================================================
Schedule_t *CMGonome::GetSchedule( void )
{
switch( m_MonsterState )
{
case MONSTERSTATE_COMBAT:
{
// dead enemy
if( HasConditions( bits_COND_ENEMY_DEAD ) )
{
// call base class, all code to handle dead enemies is centralized there.
return CMBaseMonster::GetSchedule();
}
if( HasConditions( bits_COND_NEW_ENEMY ) )
{
return GetScheduleOfType( SCHED_WAKE_ANGRY );
}
if( HasConditions( bits_COND_CAN_RANGE_ATTACK1 ) )
{
return GetScheduleOfType( SCHED_RANGE_ATTACK1 );
}
if( HasConditions( bits_COND_CAN_MELEE_ATTACK1 ) )
{
return GetScheduleOfType( SCHED_MELEE_ATTACK1 );
}
if( HasConditions( bits_COND_CAN_MELEE_ATTACK2 ) )
{
return GetScheduleOfType( SCHED_MELEE_ATTACK2 );
}
return GetScheduleOfType( SCHED_CHASE_ENEMY );
break;
}
default:
break;
}
return CMBaseMonster::GetSchedule();
}
// primary range attack
Task_t tlGonomeRangeAttack1[] =
{
{ TASK_STOP_MOVING, 0 },
{ TASK_FACE_IDEAL, (float)0 },
{ TASK_RANGE_ATTACK1, (float)0 },
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
};
Schedule_t slGonomeRangeAttack1[] =
{
{
tlGonomeRangeAttack1,
ARRAYSIZE( tlGonomeRangeAttack1 ),
bits_COND_NEW_ENEMY |
bits_COND_ENEMY_DEAD |
bits_COND_HEAVY_DAMAGE |
bits_COND_ENEMY_OCCLUDED |
bits_COND_NO_AMMO_LOADED,
0,
"Gonome Range Attack1"
},
};
// Chase enemy schedule
Task_t tlGonomeChaseEnemy1[] =
{
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_RANGE_ATTACK1 },// !!!OEM - this will stop nasty squid oscillation.
{ TASK_GET_PATH_TO_ENEMY, (float)0 },
{ TASK_RUN_PATH, (float)0 },
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
};
Schedule_t slGonomeChaseEnemy[] =
{
{
tlGonomeChaseEnemy1,
ARRAYSIZE( tlGonomeChaseEnemy1 ),
bits_COND_NEW_ENEMY |
bits_COND_ENEMY_DEAD |
bits_COND_SMELL_FOOD |
bits_COND_CAN_RANGE_ATTACK1 |
bits_COND_CAN_MELEE_ATTACK1 |
bits_COND_CAN_MELEE_ATTACK2 |
bits_COND_TASK_FAILED,
0,
"Gonome Chase Enemy"
},
};
// victory dance (eating body)
Task_t tlGonomeVictoryDance[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_WAIT, (float)0.1 },
{ TASK_GONOME_GET_PATH_TO_ENEMY_CORPSE, (float)0 },
{ TASK_WALK_PATH, (float)0 },
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
{ TASK_FACE_ENEMY, (float)0 },
{ TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE },
{ TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE },
{ TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE }
};
Schedule_t slGonomeVictoryDance[] =
{
{
tlGonomeVictoryDance,
ARRAYSIZE( tlGonomeVictoryDance ),
bits_COND_NEW_ENEMY |
bits_COND_LIGHT_DAMAGE |
bits_COND_HEAVY_DAMAGE,
0,
"GonomeVictoryDance"
},
};
DEFINE_CUSTOM_SCHEDULES( CMGonome )
{
slGonomeRangeAttack1,
slGonomeChaseEnemy,
slGonomeVictoryDance,
};
IMPLEMENT_CUSTOM_SCHEDULES( CMGonome, CMBaseMonster )
Schedule_t* CMGonome::GetScheduleOfType(int Type)
{
switch ( Type )
{
case SCHED_RANGE_ATTACK1:
return &slGonomeRangeAttack1[0];
break;
case SCHED_CHASE_ENEMY:
return &slGonomeChaseEnemy[0];
break;
case SCHED_VICTORY_DANCE:
return &slGonomeVictoryDance[0];
break;
default:
break;
}
return CMBaseMonster::GetScheduleOfType(Type);
}
void CMGonome::RunTask(Task_t *pTask)
{
// HACK to stop Gonome from playing attack sound twice
if (pTask->iTask == TASK_MELEE_ATTACK1)
{
if (!m_playedAttackSound)
{
const char* sample = NULL;
if (m_meleeAttack2)
{
sample = "gonome/gonome_melee2.wav";
}
else
{
sample = "gonome/gonome_melee1.wav";
}
EMIT_SOUND(ENT(pev), CHAN_BODY, sample, 1, ATTN_NORM);
m_playedAttackSound = true;
}
}
else
{
m_playedAttackSound = false;
}
CMBaseMonster::RunTask(pTask);
}
//=========================================================
// Start task - selects the correct activity and performs
// any necessary calculations to start the next task on the
// schedule.
//=========================================================
void CMGonome::StartTask(Task_t *pTask)
{
m_iTaskStatus = TASKSTATUS_RUNNING;
switch (pTask->iTask)
{
case TASK_GONOME_GET_PATH_TO_ENEMY_CORPSE:
{
UTIL_MakeVectors( pev->angles );
if( BuildRoute( m_vecEnemyLKP - gpGlobals->v_forward * 40, bits_MF_TO_LOCATION, NULL ) )
{
TaskComplete();
}
else
{
ALERT( at_aiconsole, "GonomeGetPathToEnemyCorpse failed!!\n" );
TaskFail();
}
}
break;
default:
CMBaseMonster::StartTask(pTask);
break;
}
}

View File

@@ -1,199 +1,199 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
/* /*
h_ai.cpp - halflife specific ai code h_ai.cpp - halflife specific ai code
*/ */
#include "extdll.h" #include "extdll.h"
#include "util.h" #include "util.h"
#include "cmbase.h" #include "cmbase.h"
#include "cmbasemonster.h" #include "cmbasemonster.h"
#include "monsters.h" #include "monsters.h"
#define NUM_LATERAL_CHECKS 13 // how many checks are made on each side of a monster looking for lateral cover #define NUM_LATERAL_CHECKS 13 // how many checks are made on each side of a monster looking for lateral cover
#define NUM_LATERAL_LOS_CHECKS 6 // how many checks are made on each side of a monster looking for lateral cover #define NUM_LATERAL_LOS_CHECKS 6 // how many checks are made on each side of a monster looking for lateral cover
//float flRandom = RANDOM_FLOAT(0,1); //float flRandom = RANDOM_FLOAT(0,1);
DLL_GLOBAL BOOL g_fDrawLines = FALSE; DLL_GLOBAL BOOL g_fDrawLines = FALSE;
//========================================================= //=========================================================
// //
// AI UTILITY FUNCTIONS // AI UTILITY FUNCTIONS
// //
// !!!UNDONE - move CBaseMonster functions to monsters.cpp // !!!UNDONE - move CBaseMonster functions to monsters.cpp
//========================================================= //=========================================================
//========================================================= //=========================================================
// FBoxVisible - a more accurate ( and slower ) version // FBoxVisible - a more accurate ( and slower ) version
// of FVisible. // of FVisible.
// //
// !!!UNDONE - make this CBaseMonster? // !!!UNDONE - make this CBaseMonster?
//========================================================= //=========================================================
BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize ) BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize )
{ {
// don't look through water // don't look through water
if ((pevLooker->waterlevel != 3 && pevTarget->waterlevel == 3) if ((pevLooker->waterlevel != 3 && pevTarget->waterlevel == 3)
|| (pevLooker->waterlevel == 3 && pevTarget->waterlevel == 0)) || (pevLooker->waterlevel == 3 && pevTarget->waterlevel == 0))
return FALSE; return FALSE;
TraceResult tr; TraceResult tr;
Vector vecLookerOrigin = pevLooker->origin + pevLooker->view_ofs;//look through the monster's 'eyes' Vector vecLookerOrigin = pevLooker->origin + pevLooker->view_ofs;//look through the monster's 'eyes'
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
Vector vecTarget = pevTarget->origin; Vector vecTarget = pevTarget->origin;
vecTarget.x += RANDOM_FLOAT( pevTarget->mins.x + flSize, pevTarget->maxs.x - flSize); vecTarget.x += RANDOM_FLOAT( pevTarget->mins.x + flSize, pevTarget->maxs.x - flSize);
vecTarget.y += RANDOM_FLOAT( pevTarget->mins.y + flSize, pevTarget->maxs.y - flSize); vecTarget.y += RANDOM_FLOAT( pevTarget->mins.y + flSize, pevTarget->maxs.y - flSize);
vecTarget.z += RANDOM_FLOAT( pevTarget->mins.z + flSize, pevTarget->maxs.z - flSize); vecTarget.z += RANDOM_FLOAT( pevTarget->mins.z + flSize, pevTarget->maxs.z - flSize);
UTIL_TraceLine(vecLookerOrigin, vecTarget, ignore_monsters, ignore_glass, ENT(pevLooker)/*pentIgnore*/, &tr); UTIL_TraceLine(vecLookerOrigin, vecTarget, ignore_monsters, ignore_glass, ENT(pevLooker)/*pentIgnore*/, &tr);
if (tr.flFraction == 1.0) if (tr.flFraction == 1.0)
{ {
vecTargetOrigin = vecTarget; vecTargetOrigin = vecTarget;
return TRUE;// line of sight is valid. return TRUE;// line of sight is valid.
} }
} }
return FALSE;// Line of sight is not established return FALSE;// Line of sight is not established
} }
// //
// VecCheckToss - returns the velocity at which an object should be lobbed from vecspot1 to land near vecspot2. // VecCheckToss - returns the velocity at which an object should be lobbed from vecspot1 to land near vecspot2.
// returns g_vecZero if toss is not feasible. // returns g_vecZero if toss is not feasible.
// //
Vector VecCheckToss ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj ) Vector VecCheckToss ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj )
{ {
TraceResult tr; TraceResult tr;
Vector vecMidPoint;// halfway point between Spot1 and Spot2 Vector vecMidPoint;// halfway point between Spot1 and Spot2
Vector vecApex;// highest point Vector vecApex;// highest point
Vector vecScale; Vector vecScale;
Vector vecGrenadeVel; Vector vecGrenadeVel;
Vector vecTemp; Vector vecTemp;
float flGravity = g_psv_gravity->value * flGravityAdj; float flGravity = g_psv_gravity->value * flGravityAdj;
if (vecSpot2.z - vecSpot1.z > 500) if (vecSpot2.z - vecSpot1.z > 500)
{ {
// to high, fail // to high, fail
return g_vecZero; return g_vecZero;
} }
UTIL_MakeVectors (pev->angles); UTIL_MakeVectors (pev->angles);
// toss a little bit to the left or right, not right down on the enemy's bean (head). // toss a little bit to the left or right, not right down on the enemy's bean (head).
vecSpot2 = vecSpot2 + gpGlobals->v_right * ( RANDOM_FLOAT(-8,8) + RANDOM_FLOAT(-16,16) ); vecSpot2 = vecSpot2 + gpGlobals->v_right * ( RANDOM_FLOAT(-8,8) + RANDOM_FLOAT(-16,16) );
vecSpot2 = vecSpot2 + gpGlobals->v_forward * ( RANDOM_FLOAT(-8,8) + RANDOM_FLOAT(-16,16) ); vecSpot2 = vecSpot2 + gpGlobals->v_forward * ( RANDOM_FLOAT(-8,8) + RANDOM_FLOAT(-16,16) );
// calculate the midpoint and apex of the 'triangle' // calculate the midpoint and apex of the 'triangle'
// UNDONE: normalize any Z position differences between spot1 and spot2 so that triangle is always RIGHT // UNDONE: normalize any Z position differences between spot1 and spot2 so that triangle is always RIGHT
// How much time does it take to get there? // How much time does it take to get there?
// get a rough idea of how high it can be thrown // get a rough idea of how high it can be thrown
vecMidPoint = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5; vecMidPoint = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5;
UTIL_TraceLine(vecMidPoint, vecMidPoint + Vector(0,0,500), ignore_monsters, ENT(pev), &tr); UTIL_TraceLine(vecMidPoint, vecMidPoint + Vector(0,0,500), ignore_monsters, ENT(pev), &tr);
vecMidPoint = tr.vecEndPos; vecMidPoint = tr.vecEndPos;
// (subtract 15 so the grenade doesn't hit the ceiling) // (subtract 15 so the grenade doesn't hit the ceiling)
vecMidPoint.z -= 15; vecMidPoint.z -= 15;
if (vecMidPoint.z < vecSpot1.z || vecMidPoint.z < vecSpot2.z) if (vecMidPoint.z < vecSpot1.z || vecMidPoint.z < vecSpot2.z)
{ {
// to not enough space, fail // to not enough space, fail
return g_vecZero; return g_vecZero;
} }
// How high should the grenade travel to reach the apex // How high should the grenade travel to reach the apex
float distance1 = (vecMidPoint.z - vecSpot1.z); float distance1 = (vecMidPoint.z - vecSpot1.z);
float distance2 = (vecMidPoint.z - vecSpot2.z); float distance2 = (vecMidPoint.z - vecSpot2.z);
// How long will it take for the grenade to travel this distance // How long will it take for the grenade to travel this distance
float time1 = sqrt( distance1 / (0.5 * flGravity) ); float time1 = sqrt( distance1 / (0.5 * flGravity) );
float time2 = sqrt( distance2 / (0.5 * flGravity) ); float time2 = sqrt( distance2 / (0.5 * flGravity) );
if (time1 < 0.1) if (time1 < 0.1)
{ {
// too close // too close
return g_vecZero; return g_vecZero;
} }
// how hard to throw sideways to get there in time. // how hard to throw sideways to get there in time.
vecGrenadeVel = (vecSpot2 - vecSpot1) / (time1 + time2); vecGrenadeVel = (vecSpot2 - vecSpot1) / (time1 + time2);
// how hard upwards to reach the apex at the right time. // how hard upwards to reach the apex at the right time.
vecGrenadeVel.z = flGravity * time1; vecGrenadeVel.z = flGravity * time1;
// find the apex // find the apex
vecApex = vecSpot1 + vecGrenadeVel * time1; vecApex = vecSpot1 + vecGrenadeVel * time1;
vecApex.z = vecMidPoint.z; vecApex.z = vecMidPoint.z;
UTIL_TraceLine(vecSpot1, vecApex, dont_ignore_monsters, ENT(pev), &tr); UTIL_TraceLine(vecSpot1, vecApex, dont_ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0) if (tr.flFraction != 1.0)
{ {
// fail! // fail!
return g_vecZero; return g_vecZero;
} }
// UNDONE: either ignore monsters or change it to not care if we hit our enemy // UNDONE: either ignore monsters or change it to not care if we hit our enemy
UTIL_TraceLine(vecSpot2, vecApex, ignore_monsters, ENT(pev), &tr); UTIL_TraceLine(vecSpot2, vecApex, ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0) if (tr.flFraction != 1.0)
{ {
// fail! // fail!
return g_vecZero; return g_vecZero;
} }
return vecGrenadeVel; return vecGrenadeVel;
} }
// //
// VecCheckThrow - returns the velocity vector at which an object should be thrown from vecspot1 to hit vecspot2. // VecCheckThrow - returns the velocity vector at which an object should be thrown from vecspot1 to hit vecspot2.
// returns g_vecZero if throw is not feasible. // returns g_vecZero if throw is not feasible.
// //
Vector VecCheckThrow ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj ) Vector VecCheckThrow ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj )
{ {
float flGravity = g_psv_gravity->value * flGravityAdj; float flGravity = g_psv_gravity->value * flGravityAdj;
Vector vecGrenadeVel = (vecSpot2 - vecSpot1); Vector vecGrenadeVel = (vecSpot2 - vecSpot1);
// throw at a constant time // throw at a constant time
float time = vecGrenadeVel.Length( ) / flSpeed; float time = vecGrenadeVel.Length( ) / flSpeed;
vecGrenadeVel = vecGrenadeVel * (1.0 / time); vecGrenadeVel = vecGrenadeVel * (1.0 / time);
// adjust upward toss to compensate for gravity loss // adjust upward toss to compensate for gravity loss
vecGrenadeVel.z += flGravity * time * 0.5; vecGrenadeVel.z += flGravity * time * 0.5;
Vector vecApex = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5; Vector vecApex = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5;
vecApex.z += 0.5 * flGravity * (time * 0.5) * (time * 0.5); vecApex.z += 0.5 * flGravity * (time * 0.5) * (time * 0.5);
TraceResult tr; TraceResult tr;
UTIL_TraceLine(vecSpot1, vecApex, dont_ignore_monsters, ENT(pev), &tr); UTIL_TraceLine(vecSpot1, vecApex, dont_ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0) if (tr.flFraction != 1.0)
{ {
// fail! // fail!
return g_vecZero; return g_vecZero;
} }
UTIL_TraceLine(vecSpot2, vecApex, ignore_monsters, ENT(pev), &tr); UTIL_TraceLine(vecSpot2, vecApex, ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0) if (tr.flFraction != 1.0)
{ {
// fail! // fail!
return g_vecZero; return g_vecZero;
} }
return vecGrenadeVel; return vecGrenadeVel;
} }

View File

@@ -1,50 +1,50 @@
// //
// Monster Mod is a modification based on Botman's original "Monster" plugin. // Monster Mod is a modification based on Botman's original "Monster" plugin.
// The "forgotten" modification was made by Rick90. // The "forgotten" modification was made by Rick90.
// This is an attempt to recreate the plugin so it does not become lost again. // This is an attempt to recreate the plugin so it does not become lost again.
// //
// Recreated by Giegue. // Recreated by Giegue.
// //
// h_export.cpp // h_export.cpp
// //
/*** /***
* *
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved. * Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
/* /*
===== h_export.cpp ======================================================== ===== h_export.cpp ========================================================
Entity classes exported by Halflife. Entity classes exported by Halflife.
*/ */
#include "extdll.h" #include "extdll.h"
#include "h_export.h" #include "h_export.h"
// From SDK dlls/h_export.cpp: // From SDK dlls/h_export.cpp:
//! Holds engine functionality callbacks //! Holds engine functionality callbacks
enginefuncs_t g_engfuncs; enginefuncs_t g_engfuncs;
globalvars_t *gpGlobals; globalvars_t *gpGlobals;
// Receive engine function table from engine. // Receive engine function table from engine.
// This appears to be the _first_ DLL routine called by the engine, so we // This appears to be the _first_ DLL routine called by the engine, so we
// do some setup operations here. // do some setup operations here.
void WINAPI GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals ) void WINAPI GiveFnptrsToDll( enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals )
{ {
memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t)); memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
gpGlobals = pGlobals; gpGlobals = pGlobals;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,384 +1,379 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
//========================================================= //=========================================================
// Hornets // Hornets
//========================================================= //=========================================================
#include "extdll.h" #include "extdll.h"
#include "util.h" #include "util.h"
#include "cmbase.h" #include "cmbase.h"
#include "cmbasemonster.h" #include "cmbasemonster.h"
#include "monsters.h" #include "monsters.h"
#include "weapons.h" #include "weapons.h"
#include "hornet.h" #include "hornet.h"
int iHornetTrail; int iHornetTrail;
int iHornetPuff; int iHornetPuff;
//========================================================= //=========================================================
// don't let hornets gib, ever. // don't let hornets gib, ever.
//========================================================= //=========================================================
int CMHornet :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) int CMHornet :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
{ {
// filter these bits a little. // filter these bits a little.
bitsDamageType &= ~ ( DMG_ALWAYSGIB ); bitsDamageType &= ~ ( DMG_ALWAYSGIB );
bitsDamageType |= DMG_NEVERGIB; bitsDamageType |= DMG_NEVERGIB;
return CMBaseMonster :: TakeDamage ( pevInflictor, pevAttacker, flDamage, bitsDamageType ); return CMBaseMonster :: TakeDamage ( pevInflictor, pevAttacker, flDamage, bitsDamageType );
} }
//========================================================= //=========================================================
//========================================================= //=========================================================
void CMHornet :: Spawn( void ) void CMHornet :: Spawn( void )
{ {
Precache(); Precache();
pev->movetype = MOVETYPE_FLY; pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_BBOX; pev->solid = SOLID_BBOX;
pev->takedamage = DAMAGE_YES; pev->takedamage = DAMAGE_YES;
pev->flags |= FL_MONSTER; // I have a bad feeling about this pev->flags |= FL_MONSTER; // I have a bad feeling about this
pev->health = 1;// weak! pev->health = 1;// weak!
// hornets don't live as long in multiplayer // hornets don't live as long in multiplayer
m_flStopAttack = gpGlobals->time + 3.5; m_flStopAttack = gpGlobals->time + 3.5;
m_flFieldOfView = 0.9; // +- 25 degrees m_flFieldOfView = 0.9; // +- 25 degrees
if ( RANDOM_LONG ( 1, 5 ) <= 2 ) if ( RANDOM_LONG ( 1, 5 ) <= 2 )
{ {
m_iHornetType = HORNET_TYPE_RED; m_iHornetType = HORNET_TYPE_RED;
m_flFlySpeed = HORNET_RED_SPEED; m_flFlySpeed = HORNET_RED_SPEED;
} }
else else
{ {
m_iHornetType = HORNET_TYPE_ORANGE; m_iHornetType = HORNET_TYPE_ORANGE;
m_flFlySpeed = HORNET_ORANGE_SPEED; m_flFlySpeed = HORNET_ORANGE_SPEED;
} }
SET_MODEL(ENT( pev ), "models/hornet.mdl"); SET_MODEL(ENT( pev ), "models/hornet.mdl");
UTIL_SetSize( pev, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ) ); UTIL_SetSize( pev, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ) );
SetTouch( &CMHornet::DieTouch ); SetTouch( &CMHornet::DieTouch );
SetThink( &CMHornet::StartTrack ); SetThink( &CMHornet::StartTrack );
edict_t *pSoundEnt = pev->owner; edict_t *pSoundEnt = pev->owner;
if ( !pSoundEnt ) if ( !pSoundEnt )
pSoundEnt = edict(); pSoundEnt = edict();
// no real owner, or owner isn't a client. // no real owner, or owner isn't a client.
pev->dmg = gSkillData.monDmgHornet; pev->dmg = gSkillData.monDmgHornet;
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
ResetSequenceInfo( ); ResetSequenceInfo( );
pev->classname = MAKE_STRING( "hornet" ); pev->classname = MAKE_STRING( "hornet" );
} }
void CMHornet :: Precache() void CMHornet :: Precache()
{ {
PRECACHE_MODEL("models/hornet.mdl"); PRECACHE_MODEL("models/hornet.mdl");
PRECACHE_SOUND( "agrunt/ag_fire1.wav" ); PRECACHE_SOUND( "agrunt/ag_fire1.wav" );
PRECACHE_SOUND( "agrunt/ag_fire2.wav" ); PRECACHE_SOUND( "agrunt/ag_fire2.wav" );
PRECACHE_SOUND( "agrunt/ag_fire3.wav" ); PRECACHE_SOUND( "agrunt/ag_fire3.wav" );
PRECACHE_SOUND( "hornet/ag_buzz1.wav" ); PRECACHE_SOUND( "hornet/ag_buzz1.wav" );
PRECACHE_SOUND( "hornet/ag_buzz2.wav" ); PRECACHE_SOUND( "hornet/ag_buzz2.wav" );
PRECACHE_SOUND( "hornet/ag_buzz3.wav" ); PRECACHE_SOUND( "hornet/ag_buzz3.wav" );
PRECACHE_SOUND( "hornet/ag_hornethit1.wav" ); PRECACHE_SOUND( "hornet/ag_hornethit1.wav" );
PRECACHE_SOUND( "hornet/ag_hornethit2.wav" ); PRECACHE_SOUND( "hornet/ag_hornethit2.wav" );
PRECACHE_SOUND( "hornet/ag_hornethit3.wav" ); PRECACHE_SOUND( "hornet/ag_hornethit3.wav" );
iHornetPuff = PRECACHE_MODEL( "sprites/muz1.spr" ); iHornetPuff = PRECACHE_MODELINDEX( "sprites/muz1.spr" );
iHornetTrail = PRECACHE_MODEL("sprites/laserbeam.spr"); iHornetTrail = PRECACHE_MODELINDEX("sprites/laserbeam.spr");
} }
//========================================================= //=========================================================
// hornets will never get mad at each other, no matter who the owner is. // hornets will never get mad at each other, no matter who the owner is.
//========================================================= //=========================================================
int CMHornet::IRelationship ( CMBaseEntity *pTarget ) int CMHornet::IRelationship ( CMBaseEntity *pTarget )
{ {
if ( pTarget->pev->modelindex == pev->modelindex ) if ( pTarget->pev->modelindex == pev->modelindex )
{ {
return R_NO; return R_NO;
} }
return CMBaseMonster :: IRelationship( pTarget ); return CMBaseMonster :: IRelationship( pTarget );
} }
//========================================================= //=========================================================
// ID's Hornet as their owner // ID's Hornet as their owner
//========================================================= //=========================================================
int CMHornet::Classify ( void ) int CMHornet::Classify ( void )
{ {
/* // Ensure classify is consistent with the owner, in the event
if ( pev->owner && pev->owner->v.flags & FL_CLIENT) // it's classification was overriden.
{ if (UTIL_IsValidEntity(pev->owner))
return CLASS_PLAYER_BIOWEAPON; {
} CMBaseMonster *pOwner = GetClassPtr((CMBaseMonster *)VARS(pev->owner));
if (pOwner)
return CLASS_ALIEN_BIOWEAPON; return pOwner->Classify();
*/ else
return pev->owner->v.iuser4;
// Ensure classify is consistent with the owner, in the event }
// it's classification was overriden. return CLASS_ALIEN_BIOWEAPON;
if ( pev->owner == NULL ) }
return CLASS_ALIEN_BIOWEAPON;
//=========================================================
// Ain't this going to make the hornets code "slow"? // StartTrack - starts a hornet out tracking its target
CMBaseMonster *pOwner = GetClassPtr((CMBaseMonster *)VARS(pev->owner)); //=========================================================
return pOwner->Classify(); void CMHornet :: StartTrack ( void )
} {
IgniteTrail();
//=========================================================
// StartTrack - starts a hornet out tracking its target SetTouch( &CMHornet::TrackTouch );
//========================================================= SetThink( &CMHornet::TrackTarget );
void CMHornet :: StartTrack ( void )
{ pev->nextthink = gpGlobals->time + 0.1;
IgniteTrail(); }
SetTouch( &CMHornet::TrackTouch ); //=========================================================
SetThink( &CMHornet::TrackTarget ); // StartDart - starts a hornet out just flying straight.
//=========================================================
pev->nextthink = gpGlobals->time + 0.1; void CMHornet :: StartDart ( void )
} {
IgniteTrail();
//=========================================================
// StartDart - starts a hornet out just flying straight. SetTouch( &CMHornet::DartTouch );
//=========================================================
void CMHornet :: StartDart ( void ) SetThink( &CMHornet::SUB_Remove );
{ pev->nextthink = gpGlobals->time + 4;
IgniteTrail(); }
SetTouch( &CMHornet::DartTouch ); void CMHornet::IgniteTrail( void )
{
SetThink( &CMHornet::SUB_Remove ); /*
pev->nextthink = gpGlobals->time + 4;
} ted's suggested trail colors:
void CMHornet::IgniteTrail( void ) r161
{ g25
/* b97
ted's suggested trail colors: r173
g39
r161 b14
g25
b97 old colors
case HORNET_TYPE_RED:
r173 WRITE_BYTE( 255 ); // r, g, b
g39 WRITE_BYTE( 128 ); // r, g, b
b14 WRITE_BYTE( 0 ); // r, g, b
break;
old colors case HORNET_TYPE_ORANGE:
case HORNET_TYPE_RED: WRITE_BYTE( 0 ); // r, g, b
WRITE_BYTE( 255 ); // r, g, b WRITE_BYTE( 100 ); // r, g, b
WRITE_BYTE( 128 ); // r, g, b WRITE_BYTE( 255 ); // r, g, b
WRITE_BYTE( 0 ); // r, g, b break;
break;
case HORNET_TYPE_ORANGE: */
WRITE_BYTE( 0 ); // r, g, b
WRITE_BYTE( 100 ); // r, g, b // trail
WRITE_BYTE( 255 ); // r, g, b MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
break; WRITE_BYTE( TE_BEAMFOLLOW );
WRITE_SHORT( entindex() ); // entity
*/ WRITE_SHORT( iHornetTrail ); // model
WRITE_BYTE( 10 ); // life
// trail WRITE_BYTE( 2 ); // width
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMFOLLOW ); switch ( m_iHornetType )
WRITE_SHORT( entindex() ); // entity {
WRITE_SHORT( iHornetTrail ); // model case HORNET_TYPE_RED:
WRITE_BYTE( 10 ); // life WRITE_BYTE( 179 ); // r, g, b
WRITE_BYTE( 2 ); // width WRITE_BYTE( 39 ); // r, g, b
WRITE_BYTE( 14 ); // r, g, b
switch ( m_iHornetType ) break;
{ case HORNET_TYPE_ORANGE:
case HORNET_TYPE_RED: WRITE_BYTE( 255 ); // r, g, b
WRITE_BYTE( 179 ); // r, g, b WRITE_BYTE( 128 ); // r, g, b
WRITE_BYTE( 39 ); // r, g, b WRITE_BYTE( 0 ); // r, g, b
WRITE_BYTE( 14 ); // r, g, b break;
break; }
case HORNET_TYPE_ORANGE:
WRITE_BYTE( 255 ); // r, g, b WRITE_BYTE( 128 ); // brightness
WRITE_BYTE( 128 ); // r, g, b
WRITE_BYTE( 0 ); // r, g, b MESSAGE_END();
break; }
}
//=========================================================
WRITE_BYTE( 128 ); // brightness // Hornet is flying, gently tracking target
//=========================================================
MESSAGE_END(); void CMHornet :: TrackTarget ( void )
} {
Vector vecFlightDir;
//========================================================= Vector vecDirToEnemy;
// Hornet is flying, gently tracking target float flDelta;
//=========================================================
void CMHornet :: TrackTarget ( void ) StudioFrameAdvance( );
{
Vector vecFlightDir; if (gpGlobals->time > m_flStopAttack)
Vector vecDirToEnemy; {
float flDelta; SetTouch( NULL );
SetThink( &CMHornet::SUB_Remove );
StudioFrameAdvance( ); pev->nextthink = gpGlobals->time + 0.1;
return;
if (gpGlobals->time > m_flStopAttack) }
{
SetTouch( NULL ); // UNDONE: The player pointer should come back after returning from another level
SetThink( &CMHornet::SUB_Remove ); if ( m_hEnemy == NULL )
pev->nextthink = gpGlobals->time + 0.1; {// enemy is dead.
return; Look( 512 );
} m_hEnemy = BestVisibleEnemy( );
}
// UNDONE: The player pointer should come back after returning from another level
if ( m_hEnemy == NULL ) if ( m_hEnemy != NULL && UTIL_FVisible( m_hEnemy, ENT(pev) ))
{// enemy is dead. {
Look( 512 ); m_vecEnemyLKP = UTIL_BodyTarget( m_hEnemy, pev->origin );
m_hEnemy = BestVisibleEnemy( ); }
} else
{
if ( m_hEnemy != NULL && UTIL_FVisible( m_hEnemy, ENT(pev) )) m_vecEnemyLKP = m_vecEnemyLKP + pev->velocity * m_flFlySpeed * 0.1;
{ }
m_vecEnemyLKP = UTIL_BodyTarget( m_hEnemy, pev->origin );
} vecDirToEnemy = ( m_vecEnemyLKP - pev->origin ).Normalize();
else
{ if (pev->velocity.Length() < 0.1)
m_vecEnemyLKP = m_vecEnemyLKP + pev->velocity * m_flFlySpeed * 0.1; vecFlightDir = vecDirToEnemy;
} else
vecFlightDir = pev->velocity.Normalize();
vecDirToEnemy = ( m_vecEnemyLKP - pev->origin ).Normalize();
// measure how far the turn is, the wider the turn, the slow we'll go this time.
if (pev->velocity.Length() < 0.1) flDelta = DotProduct ( vecFlightDir, vecDirToEnemy );
vecFlightDir = vecDirToEnemy;
else if ( flDelta < 0.5 )
vecFlightDir = pev->velocity.Normalize(); {// hafta turn wide again. play sound
switch (RANDOM_LONG(0,2))
// measure how far the turn is, the wider the turn, the slow we'll go this time. {
flDelta = DotProduct ( vecFlightDir, vecDirToEnemy ); case 0: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz1.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break;
case 1: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz2.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break;
if ( flDelta < 0.5 ) case 2: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz3.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break;
{// hafta turn wide again. play sound }
switch (RANDOM_LONG(0,2)) }
{
case 0: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz1.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break; if ( flDelta <= 0 && m_iHornetType == HORNET_TYPE_RED )
case 1: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz2.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break; {// no flying backwards, but we don't want to invert this, cause we'd go fast when we have to turn REAL far.
case 2: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_buzz3.wav", HORNET_BUZZ_VOLUME, ATTN_NORM); break; flDelta = 0.25;
} }
}
pev->velocity = ( vecFlightDir + vecDirToEnemy).Normalize();
if ( flDelta <= 0 && m_iHornetType == HORNET_TYPE_RED )
{// no flying backwards, but we don't want to invert this, cause we'd go fast when we have to turn REAL far. if ( pev->owner && (pev->owner->v.flags & FL_MONSTER) )
flDelta = 0.25; {
} // random pattern only applies to hornets fired by monsters, not players.
pev->velocity = ( vecFlightDir + vecDirToEnemy).Normalize(); pev->velocity.x += RANDOM_FLOAT ( -0.10, 0.10 );// scramble the flight dir a bit.
pev->velocity.y += RANDOM_FLOAT ( -0.10, 0.10 );
if ( pev->owner && (pev->owner->v.flags & FL_MONSTER) ) pev->velocity.z += RANDOM_FLOAT ( -0.10, 0.10 );
{ }
// random pattern only applies to hornets fired by monsters, not players.
switch ( m_iHornetType )
pev->velocity.x += RANDOM_FLOAT ( -0.10, 0.10 );// scramble the flight dir a bit. {
pev->velocity.y += RANDOM_FLOAT ( -0.10, 0.10 ); case HORNET_TYPE_RED:
pev->velocity.z += RANDOM_FLOAT ( -0.10, 0.10 ); pev->velocity = pev->velocity * ( m_flFlySpeed * flDelta );// scale the dir by the ( speed * width of turn )
} pev->nextthink = gpGlobals->time + RANDOM_FLOAT( 0.1, 0.3 );
break;
switch ( m_iHornetType ) case HORNET_TYPE_ORANGE:
{ pev->velocity = pev->velocity * m_flFlySpeed;// do not have to slow down to turn.
case HORNET_TYPE_RED: pev->nextthink = gpGlobals->time + 0.1;// fixed think time
pev->velocity = pev->velocity * ( m_flFlySpeed * flDelta );// scale the dir by the ( speed * width of turn ) break;
pev->nextthink = gpGlobals->time + RANDOM_FLOAT( 0.1, 0.3 ); }
break;
case HORNET_TYPE_ORANGE: pev->angles = UTIL_VecToAngles (pev->velocity);
pev->velocity = pev->velocity * m_flFlySpeed;// do not have to slow down to turn.
pev->nextthink = gpGlobals->time + 0.1;// fixed think time pev->solid = SOLID_BBOX;
break; }
}
//=========================================================
pev->angles = UTIL_VecToAngles (pev->velocity); // Tracking Hornet hit something
//=========================================================
pev->solid = SOLID_BBOX; void CMHornet :: TrackTouch ( edict_t *pOther )
} {
if ( (pOther == pev->owner) || pOther->v.modelindex == pev->modelindex )
//========================================================= {// bumped into the guy that shot it.
// Tracking Hornet hit something pev->solid = SOLID_NOT;
//========================================================= return;
void CMHornet :: TrackTouch ( edict_t *pOther ) }
{
if ( (pOther == pev->owner) || pOther->v.modelindex == pev->modelindex ) // is this NOT a player and IS a monster?
{// bumped into the guy that shot it. if (!UTIL_IsPlayer(pOther) && (pOther->v.flags & FL_MONSTER))
pev->solid = SOLID_NOT; {
return; CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
} if ( pMonster != NULL && IRelationship( pMonster ) <= R_NO || IRelationshipByClass( pOther->v.iuser4 ) <= R_NO )
{
// is this NOT a player and IS a monster? // hit something we don't want to hurt, so turn around.
if (!UTIL_IsPlayer(pOther) && (pOther->v.euser4 != NULL))
{ pev->velocity = pev->velocity.Normalize();
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
pev->velocity.x *= -1;
if ( IRelationship( pMonster ) <= R_NO ) pev->velocity.y *= -1;
{
// hit something we don't want to hurt, so turn around. pev->origin = pev->origin + pev->velocity * 4; // bounce the hornet off a bit.
pev->velocity = pev->velocity * m_flFlySpeed;
pev->velocity = pev->velocity.Normalize();
return;
pev->velocity.x *= -1; }
pev->velocity.y *= -1; }
pev->origin = pev->origin + pev->velocity * 4; // bounce the hornet off a bit. DieTouch( pOther );
pev->velocity = pev->velocity * m_flFlySpeed; }
return; void CMHornet::DartTouch( edict_t *pOther )
} {
} DieTouch( pOther );
}
DieTouch( pOther );
} void CMHornet::DieTouch ( edict_t *pOther )
{
void CMHornet::DartTouch( edict_t *pOther ) if ( pOther && pOther->v.takedamage )
{ {// do the damage
DieTouch( pOther );
} switch (RANDOM_LONG(0,2))
{// buzz when you plug someone
void CMHornet::DieTouch ( edict_t *pOther ) case 0: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_hornethit1.wav", 1, ATTN_NORM); break;
{ case 1: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_hornethit2.wav", 1, ATTN_NORM); break;
if ( pOther && pOther->v.takedamage ) case 2: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_hornethit3.wav", 1, ATTN_NORM); break;
{// do the damage }
switch (RANDOM_LONG(0,2)) if (UTIL_IsPlayer(pOther))
{// buzz when you plug someone UTIL_TakeDamage( pOther, pev, VARS( pev->owner ), pev->dmg, DMG_BULLET );
case 0: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_hornethit1.wav", 1, ATTN_NORM); break; else if (pOther->v.euser4 != NULL)
case 1: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_hornethit2.wav", 1, ATTN_NORM); break; {
case 2: EMIT_SOUND( ENT(pev), CHAN_VOICE, "hornet/ag_hornethit3.wav", 1, ATTN_NORM); break; CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther));
} pMonster->TakeDamage( pev, VARS( pev->owner ), pev->dmg, DMG_BULLET );
}
if (UTIL_IsPlayer(pOther)) else
UTIL_TakeDamage( pOther, pev, VARS( pev->owner ), pev->dmg, DMG_BULLET ); UTIL_TakeDamageExternal( pOther, pev, VARS( pev->owner ), pev->dmg, DMG_BULLET );
else if (pOther->v.euser4 != NULL) }
{
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pOther)); pev->modelindex = 0;// so will disappear for the 0.1 secs we wait until NEXTTHINK gets rid
pMonster->TakeDamage( pev, VARS( pev->owner ), pev->dmg, DMG_BULLET ); pev->solid = SOLID_NOT;
}
} SetThink ( &CMHornet::SUB_Remove );
pev->nextthink = gpGlobals->time + 1;// stick around long enough for the sound to finish!
pev->modelindex = 0;// so will disappear for the 0.1 secs we wait until NEXTTHINK gets rid }
pev->solid = SOLID_NOT;
SetThink ( &CMHornet::SUB_Remove );
pev->nextthink = gpGlobals->time + 1;// stick around long enough for the sound to finish!
}

View File

@@ -1,55 +1,55 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
//========================================================= //=========================================================
// Hornets // Hornets
//========================================================= //=========================================================
//========================================================= //=========================================================
// Hornet Defines // Hornet Defines
//========================================================= //=========================================================
#define HORNET_TYPE_RED 0 #define HORNET_TYPE_RED 0
#define HORNET_TYPE_ORANGE 1 #define HORNET_TYPE_ORANGE 1
#define HORNET_RED_SPEED (float)600 #define HORNET_RED_SPEED (float)600
#define HORNET_ORANGE_SPEED (float)800 #define HORNET_ORANGE_SPEED (float)800
#define HORNET_BUZZ_VOLUME (float)0.8 #define HORNET_BUZZ_VOLUME (float)0.8
extern int iHornetPuff; extern int iHornetPuff;
//========================================================= //=========================================================
// Hornet - this is the projectile that the Alien Grunt fires. // Hornet - this is the projectile that the Alien Grunt fires.
//========================================================= //=========================================================
class CMHornet : public CMBaseMonster class CMHornet : public CMBaseMonster
{ {
public: public:
void Spawn( void ); void Spawn( void );
void Precache( void ); void Precache( void );
int Classify ( void ); int Classify ( void );
int IRelationship ( CMBaseEntity *pTarget ); int IRelationship ( CMBaseEntity *pTarget );
void IgniteTrail( void ); void IgniteTrail( void );
void EXPORT StartTrack ( void ); void EXPORT StartTrack ( void );
void EXPORT StartDart ( void ); void EXPORT StartDart ( void );
void EXPORT TrackTarget ( void ); void EXPORT TrackTarget ( void );
void EXPORT TrackTouch ( edict_t *pOther ); void EXPORT TrackTouch ( edict_t *pOther );
void EXPORT DartTouch( edict_t *pOther ); void EXPORT DartTouch( edict_t *pOther );
void EXPORT DieTouch ( edict_t *pOther ); void EXPORT DieTouch ( edict_t *pOther );
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ); int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
float m_flStopAttack; float m_flStopAttack;
int m_iHornetType; int m_iHornetType;
float m_flFlySpeed; float m_flFlySpeed;
}; };

File diff suppressed because it is too large Load Diff

813
src/dlls/hwgrunt.cpp Normal file
View File

@@ -0,0 +1,813 @@
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
//=========================================================
// Heavy Weapons Grunt
//=========================================================
#include "extdll.h"
#include "plane.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "animation.h"
#include "weapons.h"
#include "cmtalkmonster.h"
#include "effects.h"
#include "customentity.h"
//=========================================================
// monster-specific DEFINE's
//=========================================================
// Weapon flags
#define HWGRUNT_MINIGUN 0
#define GUN_GROUP 1
// Gun values
#define GUN_MINIGUN 0
//=========================================================
// monster-specific schedule types
//=========================================================
enum
{
SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE = LAST_COMMON_SCHEDULE + 1,// move to a location to set up an attack against the enemy.
SCHED_HWGRUNT_REPEL,
SCHED_HWGRUNT_REPEL_LAND,
SCHED_HWGRUNT_WAIT_FACE_ENEMY,
SCHED_HWGRUNT_TAKECOVER_FAILED,// force analysis of conditions and pick the best possible schedule to recover from failure.
SCHED_HWGRUNT_ELOF_FAIL,
};
//=========================================================
// monster-specific conditions
//=========================================================
#define bits_MEMORY_HWGRUNT_SPINUP ( bits_MEMORY_CUSTOM1 )
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define HWGRUNT_AE_DEATH ( 11 )
#define HWGRUNT_AE_MINIGUN ( 5001 )
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CMHWGrunt::Classify(void)
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_HUMAN_MILITARY;
}
//=========================================================
// CheckRangeAttack1 - HWGrunt doesn't care about melee
//=========================================================
BOOL CMHWGrunt :: CheckRangeAttack1 ( float flDot, float flDist )
{
if ( !HasConditions( bits_COND_ENEMY_OCCLUDED ) && flDist <= 2048 && flDot >= 0.5 )
{
TraceResult tr;
Vector vecSrc = GetGunPosition();
// verify that a bullet fired from the gun will hit the enemy before the world.
UTIL_TraceLine( vecSrc, UTIL_BodyTarget(m_hEnemy, vecSrc), ignore_monsters, ignore_glass, ENT(pev), &tr);
if ( tr.flFraction == 1.0 )
{
return TRUE;
}
}
return FALSE;
}
//=========================================================
// CheckMeleeAttack1 - HWGrunt does not kick
//=========================================================
BOOL CMHWGrunt :: CheckMeleeAttack1 ( float flDot, float flDist )
{
return FALSE;
}
//=========================================================
// CheckRangeAttack2 - HWGrunt has no grenades
//=========================================================
BOOL CMHWGrunt :: CheckRangeAttack2 ( float flDot, float flDist )
{
return FALSE;
}
//=========================================================
// Shoot
//=========================================================
void CMHWGrunt::Minigun(void)
{
if (m_hEnemy == 0)
{
return;
}
Vector vecShootOrigin = GetGunPosition();
Vector vecShootDir = ShootAtEnemy(vecShootOrigin);
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_10DEGREES, 2048, BULLET_MONSTER_12MM); // shoot +-5 degrees
pev->effects |= EF_MUZZLEFLASH;
// Minigunners have infinite ammo
//m_cAmmoLoaded--;// take away a bullet!
Vector angDir = UTIL_VecToAngles(vecShootDir);
SetBlending(0, angDir.x);
}
//=========================================================
// TraceAttack - hwgrunts do not wear helmets
//=========================================================
void CMHWGrunt :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
{
CMBaseMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
}
//=========================================================
// TakeDamage - overridden for hwgrunts.
// They are meant to be aggresive, never take cover.
//=========================================================
int CMHWGrunt :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
{
return CMBaseMonster :: TakeDamage ( pevInflictor, pevAttacker, flDamage, bitsDamageType );
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CMHWGrunt::HandleAnimEvent(MonsterEvent_t *pEvent)
{
switch (pEvent->event)
{
case HWGRUNT_AE_DEATH:
break; // don't get rid of gun
case HWGRUNT_AE_MINIGUN:
{
// Sven Co-op uses a modified hassault/hw_gun4.wav for it's fire sound
Minigun();
// We don't want looping WAVs. Pick a different sound and change pitch on it
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "hassault/hw_shoot1.wav", 1, ATTN_NORM, 0, PITCH_NORM + RANDOM_LONG(-5,5));
}
break;
default:
CMHGrunt::HandleAnimEvent(pEvent);
break;
}
}
//=========================================================
// Spawn
//=========================================================
void CMHWGrunt::Spawn()
{
Precache();
SET_MODEL(ENT(pev), (!FStringNull( pev->model ) ? STRING( pev->model ) : "models/hwgrunt.mdl"));
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = !m_bloodColor ? BLOOD_COLOR_RED : m_bloodColor;
pev->effects = 0;
if (!pev->health) { pev->health = gSkillData.hwgruntHealth; }
m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
//m_flNextGrenadeCheck = gpGlobals->time + 1;
m_flNextPainTime = gpGlobals->time;
//m_flMinigunSpinTime = 0; // be able to spin up/down minigun right away
m_iSentence = -1;
m_fStanding = TRUE;
//m_afCapability = bits_CAP_SQUAD | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
m_afCapability = bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
//m_fEnemyEluded = FALSE;
m_fFirstEncounter = FALSE;// false because hwgrunt does not send signals of any kind
m_HackedGunPos = Vector(0, 0, 55);
// Don't setup pev->weapons, always minigun if not specified
/*
if (FBitSet(pev->weapons, HWGRUNT_MINIGUN))
{
SetBodygroup(GUN_GROUP, GUN_MINIGUN);
m_cClipSize = 1;
}
*/
m_cAmmoLoaded = 99;
m_cClipSize = 99;
CMTalkMonster::g_talkWaitTime = 0;
MonsterInit();
pev->classname = MAKE_STRING( "monster_hwgrunt" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Heavy Weapons Grunt" );
}
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CMHWGrunt::Precache()
{
PRECACHE_MODEL("models/hwgrunt.mdl");
PRECACHE_SOUND("hassault/hw_shoot1.wav");
PRECACHE_SOUND("hassault/hw_spinup.wav");
PRECACHE_SOUND("hassault/hw_spindown.wav");
// get voice pitch
m_voicePitch = 95 + RANDOM_LONG(0, 3); // slighly lower than normal grunt
CMHGrunt hgrunt;
hgrunt.Precache();
}
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
//=========================================================
// Fail
//=========================================================
Task_t tlHWGruntFail[] =
{
{ TASK_STOP_MOVING, 0 },
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
{ TASK_WAIT, (float)2 },
{ TASK_WAIT_PVS, (float)0 },
};
Schedule_t slHWGruntFail[] =
{
{
tlHWGruntFail,
ARRAYSIZE ( tlHWGruntFail ),
bits_COND_CAN_RANGE_ATTACK1,
0,
"HWGrunt Fail"
},
};
//=========================================================
// Combat Fail
//=========================================================
Task_t tlHWGruntCombatFail[] =
{
{ TASK_STOP_MOVING, 0 },
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
{ TASK_WAIT_FACE_ENEMY, (float)2 },
{ TASK_WAIT_PVS, (float)0 },
};
Schedule_t slHWGruntCombatFail[] =
{
{
tlHWGruntCombatFail,
ARRAYSIZE ( tlHWGruntCombatFail ),
bits_COND_CAN_RANGE_ATTACK1,
0,
"HWGrunt Combat Fail"
},
};
//=========================================================
// Not really victory dance
//=========================================================
Task_t tlHWGruntVictoryDance[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_FACE_ENEMY, (float)0 },
{ TASK_WAIT, (float)1.5 },
{ TASK_GET_PATH_TO_ENEMY_CORPSE, (float)0 },
{ TASK_WALK_PATH, (float)0 },
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
{ TASK_FACE_ENEMY, (float)0 },
// { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE },
};
Schedule_t slHWGruntVictoryDance[] =
{
{
tlHWGruntVictoryDance,
ARRAYSIZE ( tlHWGruntVictoryDance ),
bits_COND_NEW_ENEMY |
bits_COND_LIGHT_DAMAGE |
bits_COND_HEAVY_DAMAGE,
0,
"HWGrunt Victory Dance"
},
};
//=========================================================
// Establish line of fire - move to a position that allows
// the grunt to attack.
//=========================================================
Task_t tlHWGruntEstablishLineOfFire[] =
{
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_HWGRUNT_ELOF_FAIL },
{ TASK_GET_PATH_TO_ENEMY, (float)0 },
// { TASK_GRUNT_SPEAK_SENTENCE,(float)0 },
{ TASK_RUN_PATH, (float)0 },
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
};
Schedule_t slHWGruntEstablishLineOfFire[] =
{
{
tlHWGruntEstablishLineOfFire,
ARRAYSIZE ( tlHWGruntEstablishLineOfFire ),
bits_COND_NEW_ENEMY |
bits_COND_ENEMY_DEAD |
bits_COND_CAN_RANGE_ATTACK1 |
bits_COND_HEAR_SOUND,
0,
"HWGrunt Establish Line Of Fire"
},
};
//=========================================================
// wait in cover - we don't allow danger or the ability to
// attack to break a grunt's run to cover schedule, but when
// a grunt is in cover, we do want them to attack if they can.
//=========================================================
Task_t tlHWGruntWaitInCover[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
{ TASK_WAIT_FACE_ENEMY, (float)1 },
};
Schedule_t slHWGruntWaitInCover[] =
{
{
tlHWGruntWaitInCover,
ARRAYSIZE ( tlHWGruntWaitInCover ),
bits_COND_NEW_ENEMY |
bits_COND_HEAR_SOUND |
bits_COND_CAN_RANGE_ATTACK1,
0,
"HWGrunt Wait In Cover"
},
};
//=========================================================
// run to cover.
//=========================================================
Task_t tlHWGruntTakeCover[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_HWGRUNT_TAKECOVER_FAILED },
{ TASK_WAIT, (float)0.2 },
{ TASK_FIND_COVER_FROM_ENEMY, (float)0 },
// { TASK_GRUNT_SPEAK_SENTENCE, (float)0 },
{ TASK_RUN_PATH, (float)0 },
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
{ TASK_REMEMBER, (float)bits_MEMORY_INCOVER },
{ TASK_SET_SCHEDULE, (float)SCHED_HWGRUNT_WAIT_FACE_ENEMY },
};
Schedule_t slHWGruntTakeCover[] =
{
{
tlHWGruntTakeCover,
ARRAYSIZE ( tlHWGruntTakeCover ),
0,
0,
"HWGrunt Take Cover"
},
};
//=========================================================
// minigun spinup
//=========================================================
Task_t tlHWGruntMinigunSpinUp[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_SET_ACTIVITY, (float)ACT_THREAT_DISPLAY },
{ TASK_WAIT_FACE_ENEMY, (float)1 },
{ TASK_REMEMBER, (float)bits_MEMORY_HWGRUNT_SPINUP },
};
Schedule_t slHWGruntMinigunSpinUp[] =
{
{
tlHWGruntMinigunSpinUp,
ARRAYSIZE ( tlHWGruntMinigunSpinUp ),
0, // nothing should interrupt this
0,
"HWGrunt Minigun Spin Up"
},
};
//=========================================================
// minigun attack
//=========================================================
Task_t tlHWGruntMinigunAttack[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_RANGE_ATTACK1 },
{ TASK_RANGE_ATTACK1, (float)0 },
};
Schedule_t slHWGruntMinigunAttack[] =
{
{
tlHWGruntMinigunAttack,
ARRAYSIZE ( tlHWGruntMinigunAttack ),
bits_COND_NEW_ENEMY |
bits_COND_ENEMY_DEAD |
bits_COND_ENEMY_OCCLUDED |
bits_COND_HEAR_SOUND,
0,
"HWGrunt Minigun Attack"
},
};
//=========================================================
// repel
//=========================================================
Task_t tlHWGruntRepel[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_FACE_IDEAL, (float)0 },
{ TASK_PLAY_SEQUENCE, (float)ACT_GLIDE },
};
Schedule_t slHWGruntRepel[] =
{
{
tlHWGruntRepel,
ARRAYSIZE ( tlHWGruntRepel ),
bits_COND_SEE_ENEMY |
bits_COND_NEW_ENEMY |
bits_COND_LIGHT_DAMAGE |
bits_COND_HEAVY_DAMAGE |
bits_COND_HEAR_SOUND,
0,
"HWGrunt Repel"
},
};
//=========================================================
// repel land
//=========================================================
Task_t tlHWGruntRepelLand[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_PLAY_SEQUENCE, (float)ACT_LAND },
{ TASK_GET_PATH_TO_LASTPOSITION, (float)0 },
{ TASK_RUN_PATH, (float)0 },
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
{ TASK_CLEAR_LASTPOSITION, (float)0 },
};
Schedule_t slHWGruntRepelLand[] =
{
{
tlHWGruntRepelLand,
ARRAYSIZE ( tlHWGruntRepelLand ),
bits_COND_SEE_ENEMY |
bits_COND_NEW_ENEMY |
bits_COND_LIGHT_DAMAGE |
bits_COND_HEAVY_DAMAGE |
bits_COND_HEAR_SOUND,
0,
"HWGrunt Repel Land"
},
};
//=========================================================
// Chase enemy failure
//=========================================================
Task_t tlHWGruntChaseEnemyFailed[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_WAIT, (float)0.2 },
{ TASK_FIND_COVER_FROM_ENEMY, (float)0 },
{ TASK_RUN_PATH, (float)0 },
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
{ TASK_REMEMBER, (float)bits_MEMORY_INCOVER },
// { TASK_TURN_LEFT, (float)179 },
{ TASK_FACE_ENEMY, (float)0 },
{ TASK_WAIT, (float)1 },
};
Schedule_t slHWGruntChaseEnemyFailed[] =
{
{
tlHWGruntChaseEnemyFailed,
ARRAYSIZE ( tlHWGruntChaseEnemyFailed ),
bits_COND_NEW_ENEMY |
bits_COND_CAN_RANGE_ATTACK1 |
bits_COND_HEAR_SOUND,
0,
"HWGrunt Chase Enemy Failed"
},
};
DEFINE_CUSTOM_SCHEDULES( CMHWGrunt )
{
slHWGruntFail,
slHWGruntCombatFail,
slHWGruntVictoryDance,
slHWGruntEstablishLineOfFire,
slHWGruntWaitInCover,
slHWGruntTakeCover,
slHWGruntMinigunSpinUp,
slHWGruntMinigunAttack,
slHWGruntRepel,
slHWGruntRepelLand,
slHWGruntChaseEnemyFailed,
};
IMPLEMENT_CUSTOM_SCHEDULES( CMHWGrunt, CMBaseMonster );
//=========================================================
// SetActivity
//=========================================================
void CMHWGrunt :: SetActivity ( Activity NewActivity )
{
int iSequence = ACTIVITY_NOT_AVAILABLE;
void *pmodel = GET_MODEL_PTR( ENT(pev) );
switch ( NewActivity )
{
case ACT_RANGE_ATTACK1:
iSequence = LookupSequence( "attack" );
break;
case ACT_RUN:
iSequence = LookupSequence( "run" );
break;
case ACT_WALK:
iSequence = LookupSequence( "creeping_walk" );
break;
default:
iSequence = LookupActivity( NewActivity );
break;
}
m_Activity = NewActivity; // Go ahead and set this so it doesn't keep trying when the anim is not present
// Set to the desired anim, or default anim if the desired is not present
if ( iSequence > ACTIVITY_NOT_AVAILABLE )
{
if ( pev->sequence != iSequence || !m_fSequenceLoops )
{
pev->frame = 0;
}
pev->sequence = iSequence; // Set to the reset anim (if it's there)
ResetSequenceInfo( );
SetYawSpeed();
}
else
{
// Not available try to get default anim
ALERT ( at_console, "%s has no sequence for act:%d\n", STRING(pev->classname), NewActivity );
pev->sequence = 0; // Set to the reset anim (if it's there)
}
}
//=========================================================
// Get Schedule!
//=========================================================
Schedule_t *CMHWGrunt :: GetSchedule( void )
{
// clear old sentence
m_iSentence = -1; // we don't care about sounds for now.
// flying? If PRONE, barnacle has me. IF not, it's assumed I am rapelling.
if ( pev->movetype == MOVETYPE_FLY && m_MonsterState != MONSTERSTATE_PRONE )
{
if (pev->flags & FL_ONGROUND)
{
// just landed
pev->movetype = MOVETYPE_STEP;
return GetScheduleOfType ( SCHED_HWGRUNT_REPEL_LAND );
}
else
{
// can not attack while holding a minigun in rapel
return GetScheduleOfType ( SCHED_HWGRUNT_REPEL );
}
}
switch ( m_MonsterState )
{
case MONSTERSTATE_COMBAT:
{
// dead enemy
if ( HasConditions( bits_COND_ENEMY_DEAD ) )
{
// was attacking, spin down
if ( HasMemory( bits_MEMORY_HWGRUNT_SPINUP ) )
{
Forget( bits_MEMORY_HWGRUNT_SPINUP );
EMIT_SOUND(ENT(pev), CHAN_ITEM, "hassault/hw_spindown.wav", 0.8, ATTN_NORM);
}
// call base class, all code to handle dead enemies is centralized there.
return CMBaseMonster :: GetSchedule();
}
// new enemy
if ( HasConditions(bits_COND_NEW_ENEMY) )
{
// none of this should take place as CSquadMonster functions were completely stripped. -Giegue
/*
{
{
//!!!KELLY - the leader of a squad of grunts has just seen the player or a
// monster and has made it the squad's enemy. You
// can check pev->flags for FL_CLIENT to determine whether this is the player
// or a monster. He's going to immediately start
// firing, though. If you'd like, we can make an alternate "first sight"
// schedule where the leader plays a handsign anim
// that gives us enough time to hear a short sentence or spoken command
// before he starts pluggin away.
if (FOkToSpeak())// && RANDOM_LONG(0,1))
{
if ((m_hEnemy != NULL) && UTIL_IsPlayer(m_hEnemy))
// player
SENTENCEG_PlayRndSz( ENT(pev), "HG_ALERT", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch);
else if ((m_hEnemy != NULL) &&
(m_hEnemy->Classify() != CLASS_PLAYER_ALLY) &&
(m_hEnemy->Classify() != CLASS_HUMAN_PASSIVE) &&
(m_hEnemy->Classify() != CLASS_MACHINE))
// monster
SENTENCEG_PlayRndSz( ENT(pev), "HG_MONST", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch);
JustSpoke();
}
if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
{
return GetScheduleOfType ( SCHED_GRUNT_SUPPRESS );
}
else
{
return GetScheduleOfType ( SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE );
}
}
}
*/
}
// damaged just a little
else if ( HasConditions( bits_COND_LIGHT_DAMAGE ) )
{
// we don't want the monster to take cover when hurt while attacking, clear this
ClearConditions( bits_COND_LIGHT_DAMAGE );
}
// can shoot
else if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
{
// can fire? shoot. destroy without a care
return GetScheduleOfType( SCHED_RANGE_ATTACK1 );
}
// can't see enemy
else if ( HasConditions( bits_COND_ENEMY_OCCLUDED ) )
{
// do sound
if ( HasMemory( bits_MEMORY_HWGRUNT_SPINUP ) )
{
Forget( bits_MEMORY_HWGRUNT_SPINUP );
EMIT_SOUND(ENT(pev), CHAN_ITEM, "hassault/hw_spindown.wav", 0.8, ATTN_NORM);
}
// then go kamikaze and chase the enemy
return GetScheduleOfType( SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE );
}
if ( HasConditions( bits_COND_SEE_ENEMY ) && !HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
{
return GetScheduleOfType( SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE );
}
}
}
// no special cases here, call the base class
return CMBaseMonster :: GetSchedule();
}
//=========================================================
//=========================================================
Schedule_t* CMHWGrunt :: GetScheduleOfType ( int Type )
{
switch ( Type )
{
case SCHED_TAKE_COVER_FROM_ENEMY:
{
return &slHWGruntTakeCover[ 0 ];
}
case SCHED_HWGRUNT_TAKECOVER_FAILED:
{
if ( HasConditions( bits_COND_CAN_RANGE_ATTACK1 ) )
{
return GetScheduleOfType( SCHED_RANGE_ATTACK1 );
}
return GetScheduleOfType ( SCHED_FAIL );
}
break;
case SCHED_HWGRUNT_ELOF_FAIL:
{
// unable to move to a position that allows attacking the enemy.
return GetScheduleOfType ( SCHED_TAKE_COVER_FROM_ENEMY );
}
break;
case SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE:
{
return &slHWGruntEstablishLineOfFire[ 0 ];
}
break;
case SCHED_RANGE_ATTACK1:
{
// minigun should spin up first
if ( !HasMemory( bits_MEMORY_HWGRUNT_SPINUP ) )
{
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hassault/hw_spinup.wav", 0.8, ATTN_NORM);
return &slHWGruntMinigunSpinUp[ 0 ];
}
else
return &slHWGruntMinigunAttack[ 0 ];
}
case SCHED_HWGRUNT_WAIT_FACE_ENEMY:
{
return &slHWGruntWaitInCover[ 0 ];
}
case SCHED_VICTORY_DANCE:
{
return &slHWGruntVictoryDance[ 0 ];
}
case SCHED_FAIL:
{
if ( m_hEnemy != NULL )
{
// has an enemy, so pick a different default fail schedule most likely to help recover.
return &slHWGruntCombatFail[ 0 ];
}
return &slHWGruntFail[ 0 ];
}
case SCHED_HWGRUNT_REPEL:
{
if (pev->velocity.z > -128)
pev->velocity.z -= 32;
return &slHWGruntRepel[ 0 ];
}
case SCHED_HWGRUNT_REPEL_LAND:
{
return &slHWGruntRepelLand[ 0 ];
}
case SCHED_CHASE_ENEMY_FAILED:
{
// add missing schedule from squadmonster.cpp
return &slHWGruntChaseEnemyFailed[ 0 ];
}
default:
{
return CMBaseMonster :: GetScheduleOfType ( Type );
}
}
}

File diff suppressed because it is too large Load Diff

442
src/dlls/massn.cpp Normal file
View File

@@ -0,0 +1,442 @@
// HUGE thanks to DrBeef for his hlsdk-xash3d-opfor repository!
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
//=========================================================
// Black Ops - Male Assassin
//=========================================================
#include "extdll.h"
#include "plane.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "animation.h"
#include "weapons.h"
#include "cmtalkmonster.h"
#include "effects.h"
#include "customentity.h"
extern cvar_t *monster_default_maxrange;
//=========================================================
// monster-specific DEFINE's
//=========================================================
#define MASSN_CLIP_SIZE 36 // how many bullets in a clip? - NOTE: 3 round burst sound, so keep as 3 * x!
// Weapon flags
#define MASSN_9MMAR (1 << 0)
#define MASSN_HANDGRENADE (1 << 1)
#define MASSN_GRENADELAUNCHER (1 << 2)
#define MASSN_SNIPERRIFLE (1 << 3)
// Body groups.
#define HEAD_GROUP 1
#define GUN_GROUP 2
// Head values
#define HEAD_WHITE 0
#define HEAD_BLACK 1
#define HEAD_GOGGLES 2
// Gun values
#define GUN_MP5 0
#define GUN_SNIPERRIFLE 1
#define GUN_NONE 2
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define MASSN_AE_KICK ( 3 )
#define MASSN_AE_BURST1 ( 4 )
#define MASSN_AE_BURST2 ( 5 )
#define MASSN_AE_BURST3 ( 6 )
#define MASSN_AE_CAUGHT_ENEMY ( 10 ) // grunt established sight with an enemy (player only) that had previously eluded the squad.
#define MASSN_AE_DROP_GUN ( 11 ) // grunt (probably dead) is dropping his mp5.
//=========================================================
// Override a few behaviours to make this grunt silent
//=========================================================
BOOL CMMassn::FOkToSpeak(void)
{
return FALSE;
}
void CMMassn::IdleSound(void)
{
}
void CMMassn::PainSound(void)
{
}
void CMMassn::DeathSound(void)
{
}
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CMMassn::Classify(void)
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_HUMAN_MILITARY;
}
//=========================================================
// Shoot
//=========================================================
void CMMassn::Sniperrifle(void)
{
if (m_hEnemy == 0)
{
return;
}
Vector vecShootOrigin = GetGunPosition();
Vector vecShootDir = ShootAtEnemy(vecShootOrigin);
UTIL_MakeVectors(pev->angles);
Vector vecShellVelocity = gpGlobals->v_right * RANDOM_FLOAT(40, 90) + gpGlobals->v_up * RANDOM_FLOAT(75, 200) + gpGlobals->v_forward * RANDOM_FLOAT(-40, 40);
EjectBrass(vecShootOrigin - vecShootDir * 24, vecShellVelocity, pev->angles.y, m_iBrassShell, TE_BOUNCE_SHELL);
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_1DEGREES, 2048, BULLET_MONSTER_762, 0); // shoot +-7.5 degrees
pev->effects |= EF_MUZZLEFLASH;
m_cAmmoLoaded--;// take away a bullet!
Vector angDir = UTIL_VecToAngles(vecShootDir);
SetBlending(0, angDir.x);
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CMMassn::HandleAnimEvent(MonsterEvent_t *pEvent)
{
Vector vecShootDir;
Vector vecShootOrigin;
switch (pEvent->event)
{
case MASSN_AE_DROP_GUN:
{
Vector vecGunPos;
Vector vecGunAngles;
GetAttachment(0, vecGunPos, vecGunAngles);
// switch to body group with no gun.
SetBodygroup(GUN_GROUP, GUN_NONE);
}
break;
case MASSN_AE_BURST1:
{
if (FBitSet(pev->weapons, MASSN_9MMAR))
{
Shoot();
// the first round of the three round burst plays the sound and puts a sound in the world sound list.
if (RANDOM_LONG(0, 1))
{
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hgrunt/gr_mgun1.wav", 1, ATTN_NORM);
}
else
{
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hgrunt/gr_mgun2.wav", 1, ATTN_NORM);
}
}
else if (FBitSet(pev->weapons, MASSN_SNIPERRIFLE))
{
Sniperrifle();
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/sniper_fire.wav", 1, ATTN_NORM);
}
}
break;
case MASSN_AE_BURST2:
case MASSN_AE_BURST3:
Shoot();
break;
case MASSN_AE_KICK:
{
edict_t *pHurt = Kick();
if (pHurt)
{
// SOUND HERE!
UTIL_MakeVectors(pev->angles);
pHurt->v.punchangle.x = 15;
pHurt->v.velocity = pHurt->v.velocity + gpGlobals->v_forward * 100 + gpGlobals->v_up * 50;
if (UTIL_IsPlayer(pHurt))
UTIL_TakeDamage( pHurt, pev, pev, gSkillData.massnDmgKick, DMG_CLUB );
else if (pHurt->v.euser4 != NULL)
{
CMBaseMonster *pMonster = GetClassPtr((CMBaseMonster *)VARS(pHurt));
pMonster->TakeDamage( pev, pev, gSkillData.massnDmgKick, DMG_CLUB );
}
else
UTIL_TakeDamageExternal( pHurt, pev, pev, gSkillData.massnDmgKick, DMG_CLUB );
}
}
break;
case MASSN_AE_CAUGHT_ENEMY:
break;
default:
CMHGrunt::HandleAnimEvent(pEvent);
break;
}
}
//=========================================================
// Spawn
//=========================================================
void CMMassn::Spawn()
{
Precache();
SET_MODEL(ENT(pev), (!FStringNull( pev->model ) ? STRING( pev->model ) : "models/massn.mdl"));
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = !m_bloodColor ? BLOOD_COLOR_RED : m_bloodColor;
pev->effects = 0;
if (!pev->health) { pev->health = gSkillData.massnHealth; }
m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
m_flNextGrenadeCheck = gpGlobals->time + 1;
m_flNextPainTime = gpGlobals->time;
m_iSentence = -1;
//m_afCapability = bits_CAP_SQUAD | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
m_afCapability = bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
//m_fEnemyEluded = FALSE;
m_fFirstEncounter = TRUE;// this is true when the grunt spawns, because he hasn't encountered an enemy yet.
m_HackedGunPos = Vector(0, 0, 55);
if (pev->weapons == 0)
{
// weapons not specified, randomize
switch ( RANDOM_LONG( 0, 2 ) )
{
case 0:
pev->weapons = MASSN_9MMAR | MASSN_HANDGRENADE;
break;
case 1:
pev->weapons = MASSN_9MMAR | MASSN_GRENADELAUNCHER;
break;
case 2:
pev->weapons = MASSN_SNIPERRIFLE;
break;
}
}
if (FBitSet(pev->weapons, MASSN_SNIPERRIFLE))
{
SetBodygroup(GUN_GROUP, GUN_SNIPERRIFLE);
m_cClipSize = 5;
// if no attack range set, set 2x default
if (!m_flDistLook)
m_flDistLook = monster_default_maxrange->value * 2;
}
else
{
m_cClipSize = MASSN_CLIP_SIZE;
}
m_cAmmoLoaded = m_cClipSize;
if (RANDOM_LONG(0, 99) < 80)
pev->skin = 0; // light skin
else
pev->skin = 1; // dark skin
CMTalkMonster::g_talkWaitTime = 0;
MonsterInit();
if (FBitSet(pev->weapons, MASSN_SNIPERRIFLE))
{
// override for snipers
m_flDistTooFar = m_flDistLook / 1.33;
}
pev->classname = MAKE_STRING( "monster_male_assassin" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Male Assassin" );
}
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CMMassn::Precache()
{
PRECACHE_MODEL("models/massn.mdl");
PRECACHE_SOUND("hgrunt/gr_mgun1.wav");
PRECACHE_SOUND("hgrunt/gr_mgun2.wav");
PRECACHE_SOUND("hgrunt/gr_reload1.wav");
PRECACHE_SOUND("weapons/glauncher.wav");
PRECACHE_SOUND("weapons/sniper_bolt1.wav");
PRECACHE_SOUND("weapons/sniper_fire.wav");
PRECACHE_SOUND("zombie/claw_miss2.wav");// because we use the basemonster SWIPE animation event
// get voice pitch
if (RANDOM_LONG(0, 1))
m_voicePitch = 109 + RANDOM_LONG(0, 7);
else
m_voicePitch = 100;
m_iBrassShell = PRECACHE_MODELINDEX("models/shell.mdl");// brass shell
}
//=========================================================
// Chase enemy failure schedule
//=========================================================
Task_t tlMassnSniperAttack[] =
{
{ TASK_STOP_MOVING, (float)0 },
{ TASK_SET_ACTIVITY, (float)ACT_IDLE_ANGRY },
{ TASK_WAIT_FACE_ENEMY , (float)1 },
{ TASK_SET_ACTIVITY, (float)ACT_RANGE_ATTACK1 },
{ TASK_WAIT_FACE_ENEMY, (float)1 },
};
Schedule_t slMassnSniperAttack[] =
{
{
tlMassnSniperAttack,
ARRAYSIZE ( tlMassnSniperAttack ),
bits_COND_HEAR_SOUND,
0,
"MassnSniperAttack"
},
};
DEFINE_CUSTOM_SCHEDULES( CMMassn )
{
slMassnSniperAttack,
};
IMPLEMENT_CUSTOM_SCHEDULES( CMMassn, CMHGrunt );
//=========================================================
// SetActivity
//=========================================================
void CMMassn :: SetActivity ( Activity NewActivity )
{
int iSequence = ACTIVITY_NOT_AVAILABLE;
void *pmodel = GET_MODEL_PTR( ENT(pev) );
switch ( NewActivity )
{
case ACT_RANGE_ATTACK1:
// shooting standing or shooting crouched
if (FBitSet( pev->weapons, MASSN_SNIPERRIFLE))
{
// Always standing
iSequence = LookupSequence( "standing_m40a1" );
}
else
{
if ( m_fStanding )
{
// get aimable sequence
iSequence = LookupSequence( "standing_mp5" );
}
else
{
// get crouching shoot
iSequence = LookupSequence( "crouching_mp5" );
}
}
break;
default:
CMHGrunt::SetActivity(NewActivity);
return;
}
m_Activity = NewActivity; // Go ahead and set this so it doesn't keep trying when the anim is not present
// Set to the desired anim, or default anim if the desired is not present
if ( iSequence > ACTIVITY_NOT_AVAILABLE )
{
if ( pev->sequence != iSequence || !m_fSequenceLoops )
{
pev->frame = 0;
}
pev->sequence = iSequence; // Set to the reset anim (if it's there)
ResetSequenceInfo( );
SetYawSpeed();
}
else
{
// Not available try to get default anim
ALERT ( at_console, "%s has no sequence for act:%d\n", STRING(pev->classname), NewActivity );
pev->sequence = 0; // Set to the reset anim (if it's there)
}
}
//=========================================================
// GetScheduleOfType - Override schedule for sniper attack
//=========================================================
Schedule_t* CMMassn :: GetScheduleOfType ( int Type )
{
switch ( Type )
{
case SCHED_RANGE_ATTACK1:
{
if (FBitSet(pev->weapons, MASSN_SNIPERRIFLE))
{
// sniper attack is always standing
m_fStanding = TRUE;
return &slMassnSniperAttack[ 0 ];
}
return CMHGrunt :: GetScheduleOfType ( Type );
}
default:
{
return CMHGrunt :: GetScheduleOfType ( Type );
}
}
}

View File

@@ -1,163 +1,187 @@
// //
// Monster Mod is a modification based on Botman's original "Monster" plugin. // Monster Mod is a modification based on Botman's original "Monster" plugin.
// The "forgotten" modification was made by Rick90. // The "forgotten" modification was made by Rick90.
// This is an attempt to recreate the plugin so it does not become lost again. // This is an attempt to recreate the plugin so it does not become lost again.
// //
// Recreated by Giegue. // Recreated by Giegue.
// //
// monster_api.cpp // monster_api.cpp
// //
/* /*
* This is free software; you can redistribute it and/or modify it * This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at * Free Software Foundation; either version 2 of the License, or (at
* your option) any later version. * your option) any later version.
* *
* This is distributed in the hope that it will be useful, but * This is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this code; if not, write to the Free Software Foundation, * along with this code; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* In addition, as a special exception, the author gives permission to * In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL * link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve, * Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all * L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs * respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception * from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If * to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your * you do not wish to do so, delete this exception statement from your
* version. * version.
* *
*/ */
#include "extdll.h" #include "extdll.h"
#include "meta_api.h" #include "meta_api.h"
#include "sdk_util.h" // UTIL_LogPrintf, etc #include "sdk_util.h" // UTIL_LogPrintf, etc
// Must provide at least one of these.. // Must provide at least one of these..
static META_FUNCTIONS gMetaFunctionTable = static META_FUNCTIONS gMetaFunctionTable =
{ {
NULL, // pfnGetEntityAPI HL SDK; called before game DLL NULL, // pfnGetEntityAPI HL SDK; called before game DLL
NULL, // pfnGetEntityAPI_Post META; called after game DLL NULL, // pfnGetEntityAPI_Post META; called after game DLL
GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL
GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL
NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL
NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL
GetEngineFunctions, // pfnGetEngineFunctions META; called before HL engine NULL, // pfnGetEngineFunctions META; called before HL engine
GetEngineFunctions_Post, // pfnGetEngineFunctions_Post META; called after HL engine GetEngineFunctions_Post, // pfnGetEngineFunctions_Post META; called after HL engine
}; };
// Description of plugin // Description of plugin
plugin_info_t Plugin_info = { plugin_info_t Plugin_info = {
META_INTERFACE_VERSION, // interface version META_INTERFACE_VERSION, // interface version
"MonsterMod", // name "MonsterMod", // name
"2.0", // version "4.0", // version
"03/06/2020", // date in DD/MM/YYYY format "14/07/2023", // date in DD/MM/YYYY format
"botman, Rick90, Giegue", // original authors + recreation by... "botman, Rick90, Giegue", // original authors + recreation by...
"https://github.com/JulianR0/monstermod-redo", // url "https://github.com/JulianR0/monstermod-redo", // url
"MONSTER", // logtag "MONSTER", // logtag
PT_CHANGELEVEL, // (when) loadable PT_CHANGELEVEL, // (when) loadable
PT_CHANGELEVEL, // (when) unloadable PT_CHANGELEVEL, // (when) unloadable
}; };
char *VNAME=Plugin_info.name; char *VNAME=Plugin_info.name;
char *VVERSION=Plugin_info.version; char *VVERSION=Plugin_info.version;
char *VDATE=Plugin_info.date; char *VDATE=Plugin_info.date;
char *VAUTHOR=Plugin_info.author; char *VAUTHOR=Plugin_info.author;
char *VURL=Plugin_info.url; char *VURL=Plugin_info.url;
char *VLOGTAG=Plugin_info.logtag; char *VLOGTAG=Plugin_info.logtag;
char *COMPILE_TIME=__DATE__ ", " __TIME__; char *COMPILE_TIME=__DATE__ ", " __TIME__;
// Global vars from metamod: // Global vars from metamod:
meta_globals_t *gpMetaGlobals; // metamod globals meta_globals_t *gpMetaGlobals; // metamod globals
gamedll_funcs_t *gpGamedllFuncs; // gameDLL function tables gamedll_funcs_t *gpGamedllFuncs; // gameDLL function tables
mutil_funcs_t *gpMetaUtilFuncs; // metamod utility functions mutil_funcs_t *gpMetaUtilFuncs; // metamod utility functions
// CVars // CVars
cvar_t init_dllapi_log = {"monster_log", "0", FCVAR_EXTDLL, 0, NULL}; cvar_t init_dllapi_log = {"monster_log", "0", FCVAR_EXTDLL, 0, NULL};
cvar_t *dllapi_log = NULL; cvar_t *dllapi_log = NULL;
cvar_t init_monster_spawn = {"monster_spawn", "1", FCVAR_EXTDLL, 0, NULL}; cvar_t init_monster_spawn = {"monster_spawn", "1", FCVAR_EXTDLL, 0, NULL};
cvar_t *monster_spawn = NULL; cvar_t *monster_spawn = NULL;
cvar_t init_monster_show_deaths = {"monster_show_deaths", "1", FCVAR_EXTDLL, 0, NULL}; cvar_t init_monster_show_deaths = {"monster_show_deaths", "1", FCVAR_EXTDLL, 0, NULL};
cvar_t *monster_show_deaths = NULL; cvar_t *monster_show_deaths = NULL;
cvar_t init_monster_show_info = {"monster_show_info", "1", FCVAR_EXTDLL, 0, NULL}; cvar_t init_monster_show_info = {"monster_show_info", "1", FCVAR_EXTDLL, 0, NULL};
cvar_t *monster_show_info = NULL; cvar_t *monster_show_info = NULL;
cvar_t init_monster_turn_coeficient = {"monster_turn_coeficient", "1.75", FCVAR_EXTDLL, 0, NULL};
cvar_t *monster_turn_coeficient = NULL;
// Metamod requesting info about this plugin: cvar_t init_monster_entity_config = {"monster_entity_config", "1", FCVAR_EXTDLL, 0, NULL};
// ifvers (given) interface_version metamod is using cvar_t *monster_entity_config = NULL;
// pPlugInfo (requested) struct with info about plugin cvar_t init_globalmodellist = {"monster_gmr", "", FCVAR_EXTDLL, 0, NULL};
// pMetaUtilFuncs (given) table of utility functions provided by metamod cvar_t *globalmodellist = NULL;
C_DLLEXPORT int Meta_Query(char *ifvers, plugin_info_t **pPlugInfo, cvar_t init_globalsoundlist = {"monster_gsr", "", FCVAR_EXTDLL, 0, NULL};
mutil_funcs_t *pMetaUtilFuncs) cvar_t *globalsoundlist = NULL;
{ cvar_t init_monster_default_maxrange = {"monster_default_maxrange", "2048", FCVAR_EXTDLL, 0, NULL};
if(ifvers); // to satisfy gcc -Wunused cvar_t *monster_default_maxrange = NULL;
// Give metamod our plugin_info struct
*pPlugInfo=&Plugin_info;
// Get metamod utility function table. // Metamod requesting info about this plugin:
gpMetaUtilFuncs=pMetaUtilFuncs; // ifvers (given) interface_version metamod is using
return(TRUE); // pPlugInfo (requested) struct with info about plugin
} // pMetaUtilFuncs (given) table of utility functions provided by metamod
C_DLLEXPORT int Meta_Query(char *ifvers, plugin_info_t **pPlugInfo,
// Metamod attaching plugin to the server. mutil_funcs_t *pMetaUtilFuncs)
// now (given) current phase, ie during map, during changelevel, or at startup {
// pFunctionTable (requested) table of function tables this plugin catches if(ifvers); // to satisfy gcc -Wunused
// pMGlobals (given) global vars from metamod // Give metamod our plugin_info struct
// pGamedllFuncs (given) copy of function tables from game dll *pPlugInfo=&Plugin_info;
C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs) // Get metamod utility function table.
{ gpMetaUtilFuncs=pMetaUtilFuncs;
if(now); // to satisfy gcc -Wunused return(TRUE);
if(!pMGlobals) }
{
LOG_ERROR(PLID, "Meta_Attach called with null pMGlobals"); // Metamod attaching plugin to the server.
return(FALSE); // now (given) current phase, ie during map, during changelevel, or at startup
} // pFunctionTable (requested) table of function tables this plugin catches
gpMetaGlobals=pMGlobals; // pMGlobals (given) global vars from metamod
if(!pFunctionTable) // pGamedllFuncs (given) copy of function tables from game dll
{ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs)
LOG_ERROR(PLID, "Meta_Attach called with null pFunctionTable"); {
return(FALSE); if(now); // to satisfy gcc -Wunused
} if(!pMGlobals)
memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS)); {
gpGamedllFuncs=pGamedllFuncs; LOG_ERROR(PLID, "Meta_Attach called with null pMGlobals");
return(FALSE);
LOG_MESSAGE(PLID, "%s %s, %s", VNAME, VVERSION, VDATE); }
LOG_MESSAGE(PLID, "by %s", VAUTHOR); gpMetaGlobals=pMGlobals;
LOG_MESSAGE(PLID, "%s", VURL); if(!pFunctionTable)
LOG_MESSAGE(PLID, "compiled: %s CDT", COMPILE_TIME); {
LOG_ERROR(PLID, "Meta_Attach called with null pFunctionTable");
LOG_CONSOLE(PLID, "[%s] %s v%s, %s", VLOGTAG, VNAME, VVERSION, VDATE); return(FALSE);
LOG_CONSOLE(PLID, "[%s] by %s", VLOGTAG, VAUTHOR); }
memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS));
CVAR_REGISTER(&init_dllapi_log); gpGamedllFuncs=pGamedllFuncs;
dllapi_log = CVAR_GET_POINTER("monster_log");
LOG_MESSAGE(PLID, "%s %s, %s", VNAME, VVERSION, VDATE);
CVAR_REGISTER(&init_monster_spawn); LOG_MESSAGE(PLID, "by %s", VAUTHOR);
monster_spawn = CVAR_GET_POINTER("monster_spawn"); LOG_MESSAGE(PLID, "%s", VURL);
LOG_MESSAGE(PLID, "compiled: %s CDT", COMPILE_TIME);
CVAR_REGISTER(&init_monster_show_deaths);
monster_show_deaths = CVAR_GET_POINTER("monster_show_deaths"); LOG_CONSOLE(PLID, "[%s] %s v%s, %s", VLOGTAG, VNAME, VVERSION, VDATE);
LOG_CONSOLE(PLID, "[%s] by %s", VLOGTAG, VAUTHOR);
CVAR_REGISTER(&init_monster_show_info);
monster_show_info = CVAR_GET_POINTER("monster_show_info"); CVAR_REGISTER(&init_dllapi_log);
dllapi_log = CVAR_GET_POINTER("monster_log");
return(TRUE);
} CVAR_REGISTER(&init_monster_spawn);
monster_spawn = CVAR_GET_POINTER("monster_spawn");
extern void monster_unload(void); CVAR_REGISTER(&init_monster_show_deaths);
monster_show_deaths = CVAR_GET_POINTER("monster_show_deaths");
// Metamod detaching plugin from the server.
// now (given) current phase, ie during map, etc CVAR_REGISTER(&init_monster_show_info);
// reason (given) why detaching (refresh, console unload, forced unload, etc) monster_show_info = CVAR_GET_POINTER("monster_show_info");
C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
// remove all the monsters currently in the level... CVAR_REGISTER(&init_monster_turn_coeficient);
monster_unload(); monster_turn_coeficient = CVAR_GET_POINTER("monster_turn_coeficient");
return(TRUE);
} CVAR_REGISTER(&init_monster_entity_config);
monster_entity_config = CVAR_GET_POINTER("monster_entity_config");
CVAR_REGISTER(&init_globalmodellist);
globalmodellist = CVAR_GET_POINTER("monster_gmr");
CVAR_REGISTER(&init_globalsoundlist);
globalsoundlist = CVAR_GET_POINTER("monster_gsr");
CVAR_REGISTER(&init_monster_default_maxrange);
monster_default_maxrange = CVAR_GET_POINTER("monster_default_maxrange");
return(TRUE);
}
extern void monster_unload(void);
// Metamod detaching plugin from the server.
// now (given) current phase, ie during map, etc
// reason (given) why detaching (refresh, console unload, forced unload, etc)
C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
// remove all the monsters currently in the level...
monster_unload();
return(TRUE);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
LIBRARY monster_mm LIBRARY monster_mm
EXPORTS EXPORTS
GiveFnptrsToDll @1 GiveFnptrsToDll @1
SECTIONS SECTIONS
.data READ WRITE .data READ WRITE

View File

@@ -1,378 +0,0 @@
# Microsoft Developer Studio Project File - Name="monster_mm" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=monster_mm - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "monster_mm.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "monster_mm.mak" CFG="monster_mm - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "monster_mm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "monster_mm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "monster_mm - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "monster_mm_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\dlls" /I "..\common" /I "..\engine" /I "..\pm_shared" /I "..\..\metamod" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "monster_mm_EXPORTS" /D strcasecmp=stricmp /D strncasecmp=_strnicmp /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /def:".\monster_mm.def"
# Begin Custom Build - Copying to DLL folder
TargetPath=.\Release\monster_mm.dll
TargetName=monster_mm
InputPath=.\Release\monster_mm.dll
SOURCE="$(InputPath)"
"$(TargetName)" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetPath) D:\Half-Life\valve\dlls
copy $(TargetPath) D:\Half-Life\tfc\dlls
copy $(TargetPath) D:\Half-Life\cstrike\dlls
copy $(TargetPath) D:\Half-Life\dmc\dlls
copy $(TargetPath) D:\Half-Life\dod\dlls
copy $(TargetPath) D:\Half-Life\firearms\dlls
copy $(TargetPath) D:\Half-Life\frontline\dlls
# End Custom Build
!ELSEIF "$(CFG)" == "monster_mm - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "monster_mm_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\dlls" /I "..\common" /I "..\engine" /I "..\pm_shared" /I "..\..\metamod" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "monster_mm_EXPORTS" /D strcasecmp=stricmp /D strncasecmp=_strnicmp /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /def:".\monster_mm.def" /pdbtype:sept
# Begin Custom Build - Copying to DLL folder
TargetPath=.\Debug\monster_mm.dll
TargetName=monster_mm
InputPath=.\Debug\monster_mm.dll
SOURCE="$(InputPath)"
"$(TargetName)" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetPath) D:\Half-Life\valve\dlls
copy $(TargetPath) D:\Half-Life\tfc\dlls
copy $(TargetPath) D:\Half-Life\cstrike\dlls
copy $(TargetPath) D:\Half-Life\dmc\dlls
copy $(TargetPath) D:\Half-Life\dod\dlls
copy $(TargetPath) D:\Half-Life\firearms\dlls
copy $(TargetPath) D:\Half-Life\frontline\dlls
copy $(TargetPath) D:\Half-Life\gearbox\dlls
# End Custom Build
!ENDIF
# Begin Target
# Name "monster_mm - Win32 Release"
# Name "monster_mm - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\agrunt.cpp
# End Source File
# Begin Source File
SOURCE=.\AI_BaseNPC_Schedule.cpp
# End Source File
# Begin Source File
SOURCE=.\animating.cpp
# End Source File
# Begin Source File
SOURCE=.\animation.cpp
# End Source File
# Begin Source File
SOURCE=.\apache.cpp
# End Source File
# Begin Source File
SOURCE=.\barney.cpp
# End Source File
# Begin Source File
SOURCE=.\bigmomma.cpp
# End Source File
# Begin Source File
SOURCE=.\bullsquid.cpp
# End Source File
# Begin Source File
SOURCE=.\cmbase.cpp
# End Source File
# Begin Source File
SOURCE=.\combat.cpp
# End Source File
# Begin Source File
SOURCE=.\controller.cpp
# End Source File
# Begin Source File
SOURCE=.\defaultai.cpp
# End Source File
# Begin Source File
SOURCE=.\dllapi.cpp
# End Source File
# Begin Source File
SOURCE=.\effects.cpp
# End Source File
# Begin Source File
SOURCE=.\flyingmonster.cpp
# End Source File
# Begin Source File
SOURCE=.\ggrenade.cpp
# End Source File
# Begin Source File
SOURCE=.\h_ai.cpp
# End Source File
# Begin Source File
SOURCE=.\h_export.cpp
# End Source File
# Begin Source File
SOURCE=.\hassassin.cpp
# End Source File
# Begin Source File
SOURCE=.\headcrab.cpp
# End Source File
# Begin Source File
SOURCE=.\hgrunt.cpp
# End Source File
# Begin Source File
SOURCE=.\hornet.cpp
# End Source File
# Begin Source File
SOURCE=.\houndeye.cpp
# End Source File
# Begin Source File
SOURCE=.\islave.cpp
# End Source File
# Begin Source File
SOURCE=.\monster_api.cpp
# End Source File
# Begin Source File
SOURCE=.\monster_config.cpp
# End Source File
# Begin Source File
SOURCE=.\monsters.cpp
# End Source File
# Begin Source File
SOURCE=.\monsterstate.cpp
# End Source File
# Begin Source File
SOURCE=.\nodes.cpp
# End Source File
# Begin Source File
SOURCE=.\scientist.cpp
# End Source File
# Begin Source File
SOURCE=.\skill.cpp
# End Source File
# Begin Source File
SOURCE=.\sound.cpp
# End Source File
# Begin Source File
SOURCE=.\squeakgrenade.cpp
# End Source File
# Begin Source File
SOURCE=.\subs.cpp
# End Source File
# Begin Source File
SOURCE=.\talkmonster.cpp
# End Source File
# Begin Source File
SOURCE=.\util.cpp
# End Source File
# Begin Source File
SOURCE=.\weapons.cpp
# End Source File
# Begin Source File
SOURCE=.\zombie.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\activity.h
# End Source File
# Begin Source File
SOURCE=.\animation.h
# End Source File
# Begin Source File
SOURCE=.\cdll_dll.h
# End Source File
# Begin Source File
SOURCE=.\cmbase.h
# End Source File
# Begin Source File
SOURCE=.\cmbasemonster.h
# End Source File
# Begin Source File
SOURCE=.\cmflyingmonster.h
# End Source File
# Begin Source File
SOURCE=.\cmtalkmonster.h
# End Source File
# Begin Source File
SOURCE=.\decals.h
# End Source File
# Begin Source File
SOURCE=.\doors.h
# End Source File
# Begin Source File
SOURCE=.\effects.h
# End Source File
# Begin Source File
SOURCE=.\enginecallback.h
# End Source File
# Begin Source File
SOURCE=.\explode.h
# End Source File
# Begin Source File
SOURCE=.\extdll.h
# End Source File
# Begin Source File
SOURCE=.\func_break.h
# End Source File
# Begin Source File
SOURCE=.\monster_plugin.h
# End Source File
# Begin Source File
SOURCE=.\monsters.h
# End Source File
# Begin Source File
SOURCE=.\nodes.h
# End Source File
# Begin Source File
SOURCE=.\schedule.h
# End Source File
# Begin Source File
SOURCE=.\skill.h
# End Source File
# Begin Source File
SOURCE=.\util.h
# End Source File
# Begin Source File
SOURCE=.\vector.h
# End Source File
# Begin Source File
SOURCE=.\weapons.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

25
src/dlls/monster_mm.sln Normal file
View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.1433
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "monster_mm", "monster_mm.vcxproj", "{E4F36B30-6406-4D6E-90F6-DE34744D2434}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E4F36B30-6406-4D6E-90F6-DE34744D2434}.Debug|x86.ActiveCfg = Debug|Win32
{E4F36B30-6406-4D6E-90F6-DE34744D2434}.Debug|x86.Build.0 = Debug|Win32
{E4F36B30-6406-4D6E-90F6-DE34744D2434}.Release|x86.ActiveCfg = Release|Win32
{E4F36B30-6406-4D6E-90F6-DE34744D2434}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {32C2F544-BCE4-4787-9C16-F85467CD69DA}
EndGlobalSection
EndGlobal

230
src/dlls/monster_mm.vcxproj Normal file
View File

@@ -0,0 +1,230 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{E4F36B30-6406-4D6E-90F6-DE34744D2434}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141_xp</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<PostBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</PostBuildEventUseInBuild>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Debug/monster_mm.tlb</TypeLibraryName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\dlls;..\common;..\engine;..\pm_shared;..\metamod;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;monster_mm_EXPORTS;strcasecmp=stricmp;strncasecmp=_strnicmp;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeaderOutputFile>.\Debug/monster_mm.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
<ObjectFileName>.\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Debug/monster_mm.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ModuleDefinitionFile>.\monster_mm.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>.\Debug/monster_mm.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>.\Debug/monster_mm.lib</ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\Release/monster_mm.tlb</TypeLibraryName>
</Midl>
<ClCompile>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\dlls;..\common;..\engine;..\pm_shared;..\metamod;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;monster_mm_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeaderOutputFile>.\Release/monster_mm.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
<ObjectFileName>.\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<CompileAs>Default</CompileAs>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
<Link>
<AdditionalOptions>/MACHINE:I386 %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>.\Release/monster_mm.dll</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ModuleDefinitionFile>.\monster_mm.def</ModuleDefinitionFile>
<ProgramDatabaseFile>.\Release/monster_mm.pdb</ProgramDatabaseFile>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>.\Release/monster_mm.lib</ImportLibrary>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="agrunt.cpp" />
<ClCompile Include="AI_BaseNPC_Schedule.cpp" />
<ClCompile Include="animating.cpp" />
<ClCompile Include="animation.cpp" />
<ClCompile Include="apache.cpp" />
<ClCompile Include="barney.cpp" />
<ClCompile Include="bigmomma.cpp" />
<ClCompile Include="bullsquid.cpp" />
<ClCompile Include="cmbase.cpp" />
<ClCompile Include="combat.cpp" />
<ClCompile Include="controller.cpp" />
<ClCompile Include="defaultai.cpp" />
<ClCompile Include="dllapi.cpp" />
<ClCompile Include="effects.cpp" />
<ClCompile Include="explode.cpp" />
<ClCompile Include="flyingmonster.cpp" />
<ClCompile Include="gargantua.cpp" />
<ClCompile Include="ggrenade.cpp" />
<ClCompile Include="globalreplace.cpp" />
<ClCompile Include="gonome.cpp" />
<ClCompile Include="h_ai.cpp" />
<ClCompile Include="h_export.cpp" />
<ClCompile Include="hassassin.cpp" />
<ClCompile Include="headcrab.cpp" />
<ClCompile Include="hgrunt.cpp" />
<ClCompile Include="hornet.cpp" />
<ClCompile Include="houndeye.cpp" />
<ClCompile Include="hwgrunt.cpp" />
<ClCompile Include="islave.cpp" />
<ClCompile Include="massn.cpp" />
<ClCompile Include="monster_api.cpp" />
<ClCompile Include="monster_config.cpp" />
<ClCompile Include="monstermaker.cpp" />
<ClCompile Include="monsters.cpp" />
<ClCompile Include="monsterstate.cpp" />
<ClCompile Include="music.cpp" />
<ClCompile Include="nodes.cpp" />
<ClCompile Include="otis.cpp" />
<ClCompile Include="pitdrone.cpp" />
<ClCompile Include="rgrunt.cpp" />
<ClCompile Include="ripent.cpp" />
<ClCompile Include="scientist.cpp" />
<ClCompile Include="setcvar.cpp" />
<ClCompile Include="shock.cpp" />
<ClCompile Include="shockroach.cpp" />
<ClCompile Include="skill.cpp" />
<ClCompile Include="sound.cpp" />
<ClCompile Include="sporegrenade.cpp" />
<ClCompile Include="squeakgrenade.cpp" />
<ClCompile Include="strooper.cpp" />
<ClCompile Include="stukabat.cpp" />
<ClCompile Include="subs.cpp" />
<ClCompile Include="talkmonster.cpp" />
<ClCompile Include="turret.cpp" />
<ClCompile Include="util.cpp" />
<ClCompile Include="voltigore.cpp" />
<ClCompile Include="weapons.cpp" />
<ClCompile Include="xenmaker.cpp" />
<ClCompile Include="zombie.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="activity.h" />
<ClInclude Include="activitymap.h" />
<ClInclude Include="animation.h" />
<ClInclude Include="cdll_dll.h" />
<ClInclude Include="cmbase.h" />
<ClInclude Include="cmbaseextra.h" />
<ClInclude Include="cmbasemonster.h" />
<ClInclude Include="cmflyingmonster.h" />
<ClInclude Include="cmtalkmonster.h" />
<ClInclude Include="decals.h" />
<ClInclude Include="defaultai.h" />
<ClInclude Include="doors.h" />
<ClInclude Include="effects.h" />
<ClInclude Include="enginecallback.h" />
<ClInclude Include="explode.h" />
<ClInclude Include="extdll.h" />
<ClInclude Include="func_break.h" />
<ClInclude Include="globalreplace.h" />
<ClInclude Include="hornet.h" />
<ClInclude Include="monster_plugin.h" />
<ClInclude Include="monsterevent.h" />
<ClInclude Include="monsters.h" />
<ClInclude Include="nodes.h" />
<ClInclude Include="plane.h" />
<ClInclude Include="ripent.h" />
<ClInclude Include="schedule.h" />
<ClInclude Include="shock.h" />
<ClInclude Include="skill.h" />
<ClInclude Include="util.h" />
<ClInclude Include="vector.h" />
<ClInclude Include="weapons.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,291 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{c6c9a5d3-53c7-4dda-a7f7-a278343d08f6}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{7a512719-d6e9-4695-acde-c7239717ece9}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{af74e8b8-3ee2-4d62-b8cb-fa3952c4afed}</UniqueIdentifier>
<Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="agrunt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AI_BaseNPC_Schedule.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="animating.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="animation.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="apache.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="barney.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="bigmomma.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="bullsquid.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="cmbase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="combat.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="controller.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="defaultai.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllapi.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="effects.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="explode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="flyingmonster.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="gargantua.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ggrenade.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="gonome.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="h_ai.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="h_export.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hassassin.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="headcrab.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hgrunt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hornet.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="houndeye.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hwgrunt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="islave.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="massn.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="monster_api.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="monster_config.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="monstermaker.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="monsters.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="monsterstate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="nodes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="otis.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pitdrone.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="rgrunt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="scientist.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="shock.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="shockroach.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="skill.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sound.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sporegrenade.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="squeakgrenade.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="strooper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stukabat.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="subs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="talkmonster.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="turret.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="voltigore.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="weapons.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="zombie.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ripent.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="music.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="globalreplace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="xenmaker.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="setcvar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="activity.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="activitymap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="animation.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cdll_dll.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cmbase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cmbaseextra.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cmbasemonster.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cmflyingmonster.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cmtalkmonster.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="decals.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="defaultai.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="doors.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="effects.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="enginecallback.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="explode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="extdll.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="func_break.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hornet.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="monster_plugin.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="monsterevent.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="monsters.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="nodes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="plane.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="schedule.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="shock.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="skill.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="vector.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="weapons.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ripent.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="globalreplace.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -1,74 +1,71 @@
// //
// monster_plugin.h // monster_plugin.h
// //
#ifndef MONSTER_PLUGIN_H #ifndef MONSTER_PLUGIN_H
#define MONSTER_PLUGIN_H #define MONSTER_PLUGIN_H
typedef struct pKVD typedef struct
{ {
char key[33]; char key[33];
char value[33]; char value[481];
}; } pKVD;
#define MAX_KEYVALUES 32 #define MAX_KEYVALUES 32
typedef struct typedef struct
{ {
char *name; char *name;
bool need_to_precache; bool need_to_precache;
} monster_type_t; } monster_type_t;
class CMBaseMonster; class CMBaseMonster;
typedef struct typedef struct
{ {
int monster_index; int monster_index;
edict_t *monster_pent; edict_t *monster_pent;
bool killed; bool killed;
int respawn_index; CMBaseMonster *pMonster;
CMBaseMonster *pMonster; } monster_t;
} monster_t;
#define MAX_MONSTER_ENTS 768
#define MAX_MONSTER_ENTS 400 // increased from 200 so it can hold non-monster entities
extern monster_t monsters[MAX_MONSTER_ENTS];
extern monster_t monsters[MAX_MONSTER_ENTS];
typedef struct {
typedef struct { Vector origin;
Vector origin; Vector angles;
Vector angles; unsigned char monster;
float delay; int spawnflags;
unsigned char monster; pKVD *keyvalue;
int spawnflags; bool need_to_respawn;
pKVD *keyvalue; } monster_spawnpoint_t;
float respawn_time;
bool need_to_respawn; #define MAX_MONSTERS 384
} monster_spawnpoint_t; extern monster_spawnpoint_t monster_spawnpoint[MAX_MONSTERS];
#define MAX_MONSTERS 100 // this is here to store if a node we want to spawn is an ordinary one, or a flying one
extern monster_spawnpoint_t monster_spawnpoint[MAX_MONSTERS]; typedef struct
{
// this is here to store if a node we want to spawn is an ordinary one, or a flying one Vector origin;
typedef struct bool is_air_node;
{ } node_spawnpoint_t;
Vector origin;
bool is_air_node; // nodes.cpp defines 1024 max nodes, but that amount is likely to trigger a
} node_spawnpoint_t; // no free edicts crash if the server num_edicts is low. Increase if needed.
#define MAX_NODES 256
// nodes.cpp defines 1024 max nodes, but that amount is likely to trigger a extern node_spawnpoint_t node_spawnpoint[MAX_NODES];
// no free edicts crash if the server num_edicts is low. Increase if needed.
#define MAX_NODES 256 extern DLL_GLOBAL short g_sModelIndexFireball;// holds the index for the fireball
extern node_spawnpoint_t node_spawnpoint[MAX_NODES]; extern DLL_GLOBAL short g_sModelIndexSmoke;// holds the index for the smoke cloud
extern DLL_GLOBAL short g_sModelIndexWExplosion;// holds the index for the underwater explosion
extern DLL_GLOBAL short g_sModelIndexFireball;// holds the index for the fireball extern DLL_GLOBAL short g_sModelIndexBubbles;// holds the index for the bubbles model
extern DLL_GLOBAL short g_sModelIndexSmoke;// holds the index for the smoke cloud extern DLL_GLOBAL short g_sModelIndexBloodDrop;// holds the sprite index for the initial blood
extern DLL_GLOBAL short g_sModelIndexWExplosion;// holds the index for the underwater explosion extern DLL_GLOBAL short g_sModelIndexBloodSpray;// holds the sprite index for splattered blood
extern DLL_GLOBAL short g_sModelIndexBubbles;// holds the index for the bubbles model extern DLL_GLOBAL short g_sModelIndexLaser;// holds the index for the laser beam
extern DLL_GLOBAL short g_sModelIndexBloodDrop;// holds the sprite index for the initial blood extern DLL_GLOBAL const char *g_pModelNameLaser;
extern DLL_GLOBAL short g_sModelIndexBloodSpray;// holds the sprite index for splattered blood extern DLL_GLOBAL short g_sModelIndexLaserDot;// holds the index for the laser beam dot
extern DLL_GLOBAL short g_sModelIndexLaser;// holds the index for the laser beam
extern DLL_GLOBAL const char *g_pModelNameLaser; #endif
extern DLL_GLOBAL short g_sModelIndexLaserDot;// holds the index for the laser beam dot
#endif

View File

@@ -1,34 +1,34 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef MONSTEREVENT_H #ifndef MONSTEREVENT_H
#define MONSTEREVENT_H #define MONSTEREVENT_H
typedef struct typedef struct
{ {
int event; int event;
char *options; char *options;
} MonsterEvent_t; } MonsterEvent_t;
#define EVENT_SPECIFIC 0 #define EVENT_SPECIFIC 0
#define EVENT_SCRIPTED 1000 #define EVENT_SCRIPTED 1000
#define EVENT_SHARED 2000 #define EVENT_SHARED 2000
#define EVENT_CLIENT 5000 #define EVENT_CLIENT 5000
#define MONSTER_EVENT_BODYDROP_LIGHT 2001 #define MONSTER_EVENT_BODYDROP_LIGHT 2001
#define MONSTER_EVENT_BODYDROP_HEAVY 2002 #define MONSTER_EVENT_BODYDROP_HEAVY 2002
#define MONSTER_EVENT_SWISHSOUND 2010 #define MONSTER_EVENT_SWISHSOUND 2010
#endif // MONSTEREVENT_H #endif // MONSTEREVENT_H

366
src/dlls/monstermaker.cpp Normal file
View File

@@ -0,0 +1,366 @@
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
//=========================================================
// Monster Maker - this is an entity that creates monsters
// in the game.
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbaseextra.h"
#include "monsters.h"
// Monstermaker spawnflags
#define SF_MONSTERMAKER_START_ON 1 // start active ( if has targetname )
#define SF_MONSTERMAKER_CYCLIC 4 // drop one monster every time fired.
#define SF_MONSTERMAKER_MONSTERCLIP 8 // Children are blocked by monsterclip
#define SF_MONSTERMAKER_PRISONER 16 // children won't attack or be attacked
extern monster_type_t monster_types[];
extern edict_t* spawn_monster(int monster_type, Vector origin, Vector angles, int spawnflags, pKVD *keyvalue);
// ========================================================
void CMMonsterMaker :: KeyValue( KeyValueData *pkvd )
{
if ( FStrEq(pkvd->szKeyName, "monstercount") )
{
m_cNumMonsters = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "m_imaxlivechildren") )
{
m_iMaxLiveChildren = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "monstertype") )
{
// Process monster_index
int mIndex;
for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++)
{
if (strcmp(pkvd->szValue, monster_types[mIndex].name) == 0)
{
m_iMonsterIndex = mIndex;
break; // grab the first entry we find
}
}
if (monster_types[mIndex].name[0] == 0)
{
ALERT ( at_logged, "[MONSTER] MonsterMaker - %s is not a valid monster type!\n", pkvd->szValue );
m_iMonsterIndex = -1;
}
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "new_model") )
{
m_iszCustomModel = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "bloodcolor") )
{
m_iMonsterBlood = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "respawn_as_playerally") )
{
if (atoi(pkvd->szValue))
m_iClassifyOverride = CLASS_PLAYER_ALLY;
pkvd->fHandled = TRUE;
}
// These are to keep consistency with Sven Co-op's squadmaker entity.
// CMBaseMonster::KeyValue will process TriggerCondition/TriggerTarget
// keyvalues in the same way.
else if ( FStrEq(pkvd->szKeyName, "trigger_condition") )
{
m_iTriggerCondition = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "trigger_target") )
{
m_iszTriggerTarget = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CMBaseMonster::KeyValue( pkvd );
}
void CMMonsterMaker :: Spawn( )
{
// likely omitted keyvalue, but it could truly be an alien grunt spawn
if ( m_iMonsterIndex == 0 )
{
if ( !monster_types[0].need_to_precache )
{
// monstertype was not defined
ALERT ( at_logged, "[MONSTER] Spawned a monstermaker entity without a monstertype! targetname: \"%s\"\n", STRING(pev->targetname) );
m_iMonsterIndex = -1;
}
}
pev->solid = SOLID_NOT;
m_cLiveChildren = 0;
Precache();
if ( !FStringNull ( pev->targetname ) )
{
if ( pev->spawnflags & SF_MONSTERMAKER_CYCLIC )
{
SetUse ( &CMMonsterMaker::CyclicUse );// drop one monster each time we fire
}
else
{
SetUse ( &CMMonsterMaker::ToggleUse );// so can be turned on/off
}
if ( FBitSet ( pev->spawnflags, SF_MONSTERMAKER_START_ON ) )
{// start making monsters as soon as monstermaker spawns
m_fActive = TRUE;
SetThink ( &CMMonsterMaker::MakerThink );
}
else
{// wait to be activated.
m_fActive = FALSE;
SetThink ( &CMMonsterMaker::SUB_DoNothing );
}
}
else
{// no targetname, just start.
pev->nextthink = gpGlobals->time + m_flDelay;
m_fActive = TRUE;
SetThink ( &CMMonsterMaker::MakerThink );
}
// always fade
m_fFadeChildren = TRUE;
m_flGround = 0;
pev->classname = MAKE_STRING("monstermaker");
}
void CMMonsterMaker :: Precache( void )
{
CMBaseMonster::Precache();
// choosen monster is auto-precached
}
//=========================================================
// MakeMonster- this is the code that drops the monster
//=========================================================
void CMMonsterMaker::MakeMonster( void )
{
// monstermaker incorrectly setup or intentionally empty
if ( m_iMonsterIndex == -1 )
{
ALERT ( at_console, "[MONSTER] NULL Ent in MonsterMaker!\n" );
return;
}
edict_t *pent;
pKVD keyvalue[MAX_KEYVALUES];
int createSF = SF_MONSTER_FALL_TO_GROUND;
if ( m_iMaxLiveChildren > 0 && m_cLiveChildren >= m_iMaxLiveChildren )
{// not allowed to make a new one yet. Too many live ones out right now.
return;
}
if ( !m_flGround )
{
// set altitude. Now that I'm activated, any breakables, etc should be out from under me.
TraceResult tr;
UTIL_TraceLine ( pev->origin, pev->origin - Vector ( 0, 0, 2048 ), ignore_monsters, ENT(pev), &tr );
m_flGround = tr.vecEndPos.z;
}
Vector mins = pev->origin - Vector( 34, 34, 0 );
Vector maxs = pev->origin + Vector( 34, 34, 0 );
maxs.z = pev->origin.z;
mins.z = m_flGround;
edict_t *pList[2];
int count = UTIL_EntitiesInBox( pList, 2, mins, maxs, FL_CLIENT|FL_MONSTER );
if ( count )
{
// don't build a stack of monsters!
return;
}
// Should children hit monsterclip brushes?
if ( pev->spawnflags & SF_MONSTERMAKER_MONSTERCLIP )
createSF |= SF_MONSTER_HITMONSTERCLIP;
// Should children be prisoner entities?
if (pev->spawnflags & SF_MONSTERMAKER_PRISONER)
createSF |= SF_MONSTER_PRISONER;
/* KEYVALUES */
// Monster is to have a custom model?
if ( !FStringNull( m_iszCustomModel ) )
{
// setup model keyvalue
strcpy(keyvalue[0].key, "model");
strcpy(keyvalue[0].value, STRING( m_iszCustomModel ));
}
// Override monster blood color?
if ( m_iMonsterBlood )
{
// setup blood keyvalue
strcpy(keyvalue[1].key, "bloodcolor");
sprintf(keyvalue[1].value, "%i", m_iMonsterBlood);
}
// Trigger conditions set?
if ( !FStringNull( m_iszTriggerTarget ) )
{
// setup trigger keyvalues
strcpy(keyvalue[2].key, "TriggerCondition");
sprintf(keyvalue[2].value, "%i", m_iTriggerCondition);
strcpy(keyvalue[3].key, "TriggerTarget");
strcpy(keyvalue[3].value, STRING( m_iszTriggerTarget ));
}
// Weapons (For hgrunt/massn/rgrunt/etc...)
if ( pev->weapons )
{
strcpy(keyvalue[4].key, "weapons");
sprintf(keyvalue[4].value, "%i", pev->weapons);
}
// Monster's Name
if ( !FStringNull( m_szMonsterName ) )
{
strcpy(keyvalue[5].key, "displayname");
strcpy(keyvalue[5].value, STRING( m_szMonsterName ));
}
// Classify override
if ( m_iClassifyOverride )
{
strcpy(keyvalue[6].key, "classify");
sprintf(keyvalue[6].value, "%i", m_iClassifyOverride);
}
// Custom health
if (pev->health)
{
strcpy(keyvalue[7].key, "health");
sprintf(keyvalue[7].value, "%f", pev->health);
}
// Attempt to spawn monster
pent = spawn_monster(m_iMonsterIndex, pev->origin, pev->angles, createSF, keyvalue);
if ( pent == NULL )
{
ALERT ( at_console, "[MONSTER] MonsterMaker - failed to spawn monster! targetname: \"%s\"\n", STRING(pev->targetname) );
return;
}
// If I have a target, fire!
if ( !FStringNull ( pev->target ) )
{
// delay already overloaded for this entity, so can't call SUB_UseTargets()
FireTargets( STRING(pev->target), this->edict(), this->edict(), USE_TOGGLE, 0 );
}
pent->v.owner = edict();
if ( !FStringNull( pev->netname ) )
{
// if I have a netname (overloaded), give the child monster that name as a targetname
pent->v.targetname = pev->netname;
}
// Pass parent's rendering effects to child
pent->v.rendermode = pev->rendermode;
pent->v.renderfx = pev->renderfx;
pent->v.renderamt = pev->renderamt;
pent->v.rendercolor = pev->rendercolor;
// Soundlist isn't "exactly" a keyvalue so pass it here
if (m_srSoundList != NULL)
{
// it needs to be allocated first
CMBaseMonster *pChild = GetClassPtr((CMBaseMonster *)VARS(pent));
pChild->m_srSoundList = (REPLACER::REPLACER*)calloc(MAX_REPLACEMENTS, sizeof(*pChild->m_srSoundList));
memcpy(pChild->m_srSoundList, m_srSoundList, m_isrSounds * sizeof(*pChild->m_srSoundList));
pChild->m_isrSounds = m_isrSounds;
}
m_cLiveChildren++;// count this monster
m_cNumMonsters--;
if ( m_cNumMonsters == 0 )
{
// Disable this forever. Don't kill it because it still gets death notices
SetThink( NULL );
SetUse( NULL );
}
}
//=========================================================
// CyclicUse - drops one monster from the monstermaker
// each time we call this.
//=========================================================
void CMMonsterMaker::CyclicUse ( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
{
MakeMonster();
}
//=========================================================
// ToggleUse - activates/deactivates the monster maker
//=========================================================
void CMMonsterMaker :: ToggleUse ( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
{
if ( !ShouldToggle( useType, m_fActive ) )
return;
if ( m_fActive )
{
m_fActive = FALSE;
SetThink ( NULL );
}
else
{
m_fActive = TRUE;
SetThink ( &CMMonsterMaker::MakerThink );
}
pev->nextthink = gpGlobals->time;
}
//=========================================================
// MakerThink - creates a new monster every so often
//=========================================================
void CMMonsterMaker :: MakerThink ( void )
{
pev->nextthink = gpGlobals->time + m_flDelay;
MakeMonster();
}
//=========================================================
//=========================================================
void CMMonsterMaker :: DeathNotice ( entvars_t *pevChild )
{
// ok, we've gotten the deathnotice from our child, now clear out its owner if we don't want it to fade.
m_cLiveChildren--;
if ( !m_fFadeChildren )
{
pevChild->owner = NULL;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,180 +1,181 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* This source code contains proprietary and confidential information of * This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to * Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access, * persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal. * use or distribution of this code by or to any unlicensed person is illegal.
* *
****/ ****/
#ifndef MONSTERS_H #ifndef MONSTERS_H
#define MONSTERS_H #define MONSTERS_H
/* /*
===== monsters.h ======================================================== ===== monsters.h ========================================================
Header file for monster-related utility code Header file for monster-related utility code
*/ */
// CHECKLOCALMOVE result types // CHECKLOCALMOVE result types
#define LOCALMOVE_INVALID 0 // move is not possible #define LOCALMOVE_INVALID 0 // move is not possible
#define LOCALMOVE_INVALID_DONT_TRIANGULATE 1 // move is not possible, don't try to triangulate #define LOCALMOVE_INVALID_DONT_TRIANGULATE 1 // move is not possible, don't try to triangulate
#define LOCALMOVE_VALID 2 // move is possible #define LOCALMOVE_VALID 2 // move is possible
// Hit Group standards // Hit Group standards
#define HITGROUP_GENERIC 0 #define HITGROUP_GENERIC 0
#define HITGROUP_HEAD 1 #define HITGROUP_HEAD 1
#define HITGROUP_CHEST 2 #define HITGROUP_CHEST 2
#define HITGROUP_STOMACH 3 #define HITGROUP_STOMACH 3
#define HITGROUP_LEFTARM 4 #define HITGROUP_LEFTARM 4
#define HITGROUP_RIGHTARM 5 #define HITGROUP_RIGHTARM 5
#define HITGROUP_LEFTLEG 6 #define HITGROUP_LEFTLEG 6
#define HITGROUP_RIGHTLEG 7 #define HITGROUP_RIGHTLEG 7
// Monster Spawnflags // Monster Spawnflags
#define SF_MONSTER_WAIT_TILL_SEEN 1// spawnflag that makes monsters wait until player can see them before attacking. #define SF_MONSTER_WAIT_TILL_SEEN 1// spawnflag that makes monsters wait until player can see them before attacking.
#define SF_MONSTER_GAG 2 // no idle noises from this monster #define SF_MONSTER_GAG 2 // no idle noises from this monster
#define SF_MONSTER_HITMONSTERCLIP 4 #define SF_MONSTER_HITMONSTERCLIP 4
// 8 // 8
#define SF_MONSTER_PRISONER 16 // monster won't attack anyone, no one will attacke him. #define SF_MONSTER_PRISONER 16 // monster won't attack anyone, no one will attacke him.
// 32 // 32
// 64 // 64
#define SF_MONSTER_WAIT_FOR_SCRIPT 128 //spawnflag that makes monsters wait to check for attacking until the script is done or they've been attacked #define SF_MONSTER_WAIT_FOR_SCRIPT 128 //spawnflag that makes monsters wait to check for attacking until the script is done or they've been attacked
#define SF_MONSTER_PREDISASTER 256 //this is a predisaster scientist or barney. Influences how they speak. #define SF_MONSTER_PREDISASTER 256 //this is a predisaster scientist or barney. Influences how they speak.
#define SF_MONSTER_FADECORPSE 512 // Fade out corpse after death #define SF_MONSTER_FADECORPSE 512 // Fade out corpse after death
#define SF_MONSTER_FALL_TO_GROUND 0x80000000 #define SF_MONSTER_FALL_TO_GROUND 0x80000000
// specialty spawnflags // specialty spawnflags
#define SF_MONSTER_TURRET_AUTOACTIVATE 32 #define SF_MONSTER_TURRET_AUTOACTIVATE 32
#define SF_MONSTER_TURRET_STARTINACTIVE 64 #define SF_MONSTER_TURRET_STARTINACTIVE 64
#define SF_MONSTER_WAIT_UNTIL_PROVOKED 64 // don't attack the player unless provoked #define SF_MONSTER_WAIT_UNTIL_PROVOKED 64 // don't attack the player unless provoked
// MoveToOrigin stuff // MoveToOrigin stuff
#define MOVE_START_TURN_DIST 64 // when this far away from moveGoal, start turning to face next goal #define MOVE_START_TURN_DIST 64 // when this far away from moveGoal, start turning to face next goal
#define MOVE_STUCK_DIST 32 // if a monster can't step this far, it is stuck. #define MOVE_STUCK_DIST 32 // if a monster can't step this far, it is stuck.
// MoveToOrigin stuff // MoveToOrigin stuff
#define MOVE_NORMAL 0// normal move in the direction monster is facing #define MOVE_NORMAL 0// normal move in the direction monster is facing
#define MOVE_STRAFE 1// moves in direction specified, no matter which way monster is facing #define MOVE_STRAFE 1// moves in direction specified, no matter which way monster is facing
// spawn flags 256 and above are already taken by the engine // spawn flags 256 and above are already taken by the engine
extern void UTIL_MoveToOrigin( edict_t* pent, const Vector &vecGoal, float flDist, int iMoveType ); extern void UTIL_MoveToOrigin( edict_t* pent, const Vector &vecGoal, float flDist, int iMoveType );
Vector VecCheckToss ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj = 1.0 ); Vector VecCheckToss ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flGravityAdj = 1.0 );
Vector VecCheckThrow ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj = 1.0 ); Vector VecCheckThrow ( entvars_t *pev, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj = 1.0 );
extern DLL_GLOBAL Vector g_vecAttackDir; extern DLL_GLOBAL Vector g_vecAttackDir;
extern DLL_GLOBAL CONSTANT float g_flMeleeRange; extern DLL_GLOBAL CONSTANT float g_flMeleeRange;
extern DLL_GLOBAL CONSTANT float g_flMediumRange; extern DLL_GLOBAL CONSTANT float g_flMediumRange;
extern DLL_GLOBAL CONSTANT float g_flLongRange; extern DLL_GLOBAL CONSTANT float g_flLongRange;
extern void EjectBrass (const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype ); extern void EjectBrass (const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype );
extern void ExplodeModel( const Vector &vecOrigin, float speed, int model, int count ); extern void ExplodeModel( const Vector &vecOrigin, float speed, int model, int count );
BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget ); BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget );
BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize = 0.0 ); BOOL FBoxVisible ( entvars_t *pevLooker, entvars_t *pevTarget, Vector &vecTargetOrigin, float flSize = 0.0 );
// monster to monster relationship types // monster to monster relationship types
#define R_AL -2 // (ALLY) pals. Good alternative to R_NO when applicable. #define R_AL -2 // (ALLY) pals. Good alternative to R_NO when applicable.
#define R_FR -1// (FEAR)will run #define R_FR -1// (FEAR)will run
#define R_NO 0// (NO RELATIONSHIP) disregard #define R_NO 0// (NO RELATIONSHIP) disregard
#define R_DL 1// (DISLIKE) will attack #define R_DL 1// (DISLIKE) will attack
#define R_HT 2// (HATE)will attack this character instead of any visible DISLIKEd characters #define R_HT 2// (HATE)will attack this character instead of any visible DISLIKEd characters
#define R_NM 3// (NEMESIS) A monster Will ALWAYS attack its nemsis, no matter what #define R_NM 3// (NEMESIS) A monster Will ALWAYS attack its nemsis, no matter what
// these bits represent the monster's memory // these bits represent the monster's memory
#define MEMORY_CLEAR 0 #define MEMORY_CLEAR 0
#define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes. #define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes.
#define bits_MEMORY_INCOVER ( 1 << 1 )// monster knows it is in a covered position. #define bits_MEMORY_INCOVER ( 1 << 1 )// monster knows it is in a covered position.
#define bits_MEMORY_SUSPICIOUS ( 1 << 2 )// Ally is suspicious of the player, and will move to provoked more easily #define bits_MEMORY_SUSPICIOUS ( 1 << 2 )// Ally is suspicious of the player, and will move to provoked more easily
#define bits_MEMORY_PATH_FINISHED ( 1 << 3 )// Finished monster path (just used by big momma for now) #define bits_MEMORY_PATH_FINISHED ( 1 << 3 )// Finished monster path (just used by big momma for now)
#define bits_MEMORY_ON_PATH ( 1 << 4 )// Moving on a path #define bits_MEMORY_ON_PATH ( 1 << 4 )// Moving on a path
#define bits_MEMORY_MOVE_FAILED ( 1 << 5 )// Movement has already failed #define bits_MEMORY_MOVE_FAILED ( 1 << 5 )// Movement has already failed
#define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched #define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched
#define bits_MEMORY_KILLED ( 1 << 7 )// HACKHACK -- remember that I've already called my Killed() #define bits_MEMORY_KILLED ( 1 << 7 )// HACKHACK -- remember that I've already called my Killed()
#define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // Monster-specific memory #define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // Monster-specific memory
#define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // Monster-specific memory #define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // Monster-specific memory
#define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // Monster-specific memory #define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // Monster-specific memory
#define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // Monster-specific memory #define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // Monster-specific memory
// trigger conditions for scripted AI // trigger conditions for scripted AI
// these MUST match the CHOICES interface in halflife.fgd for the base monster // these MUST match the CHOICES interface in halflife.fgd for the base monster
enum enum
{ {
AITRIGGER_NONE = 0, AITRIGGER_NONE = 0,
AITRIGGER_SEEPLAYER_ANGRY_AT_PLAYER, AITRIGGER_SEEPLAYER_ANGRY_AT_PLAYER,
AITRIGGER_TAKEDAMAGE, AITRIGGER_TAKEDAMAGE,
AITRIGGER_HALFHEALTH, AITRIGGER_HALFHEALTH,
AITRIGGER_DEATH, AITRIGGER_DEATH,
AITRIGGER_SQUADMEMBERDIE, AITRIGGER_SQUADMEMBERDIE,
AITRIGGER_SQUADLEADERDIE, AITRIGGER_SQUADLEADERDIE,
AITRIGGER_HEARWORLD, AITRIGGER_HEARWORLD,
AITRIGGER_HEARPLAYER, AITRIGGER_HEARPLAYER,
AITRIGGER_HEARCOMBAT, AITRIGGER_HEARCOMBAT,
AITRIGGER_SEEPLAYER_UNCONDITIONAL, AITRIGGER_SEEPLAYER_UNCONDITIONAL,
AITRIGGER_SEEPLAYER_NOT_IN_COMBAT, AITRIGGER_SEEPLAYER_NOT_IN_COMBAT,
}; };
/* /*
0 : "No Trigger" 0 : "No Trigger"
1 : "See Player" 1 : "See Player"
2 : "Take Damage" 2 : "Take Damage"
3 : "50% Health Remaining" 3 : "50% Health Remaining"
4 : "Death" 4 : "Death"
5 : "Squad Member Dead" 5 : "Squad Member Dead"
6 : "Squad Leader Dead" 6 : "Squad Leader Dead"
7 : "Hear World" 7 : "Hear World"
8 : "Hear Player" 8 : "Hear Player"
9 : "Hear Combat" 9 : "Hear Combat"
*/ */
// //
// A gib is a chunk of a body, or a piece of wood/metal/rocks/etc. // A gib is a chunk of a body, or a piece of wood/metal/rocks/etc.
// //
class CMGib : public CMBaseEntity class CMGib : public CMBaseEntity
{ {
public: public:
void Spawn( const char *szGibModel ); void Spawn( const char *szGibModel );
void EXPORT BounceGibTouch ( edict_t *pOther ); void EXPORT BounceGibTouch ( edict_t *pOther );
void EXPORT StickyGibTouch ( edict_t *pOther ); void EXPORT StickyGibTouch ( edict_t *pOther );
void EXPORT WaitTillLand( void ); void EXPORT WaitTillLand( void );
void LimitVelocity( void ); void LimitVelocity( void );
virtual int ObjectCaps( void ) { return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE; } virtual int ObjectCaps( void ) { return (CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE; }
static void SpawnHeadGib( entvars_t *pevVictim ); static void SpawnHeadGib( entvars_t *pevVictim );
static void SpawnRandomGibs( entvars_t *pevVictim, int cGibs, int human ); static void SpawnRandomGibs( entvars_t *pevVictim, int cGibs, int human );
static void SpawnStickyGibs( entvars_t *pevVictim, Vector vecOrigin, int cGibs ); static void SpawnRandomGibs( entvars_t *pevVictim, int cGibs, const char *pGibModel, int human );
static void SpawnStickyGibs( entvars_t *pevVictim, Vector vecOrigin, int cGibs );
int m_bloodColor;
int m_cBloodDecals; int m_bloodColor;
int m_material; int m_cBloodDecals;
float m_lifeTime; int m_material;
}; float m_lifeTime;
};
#define CUSTOM_SCHEDULES\
virtual Schedule_t *ScheduleFromName( const char *pName );\ #define CUSTOM_SCHEDULES\
static Schedule_t *m_scheduleList[]; virtual Schedule_t *ScheduleFromName( const char *pName );\
static Schedule_t *m_scheduleList[];
#define DEFINE_CUSTOM_SCHEDULES(derivedClass)\
Schedule_t *derivedClass::m_scheduleList[] = #define DEFINE_CUSTOM_SCHEDULES(derivedClass)\
Schedule_t *derivedClass::m_scheduleList[] =
#define IMPLEMENT_CUSTOM_SCHEDULES(derivedClass, baseClass)\
Schedule_t *derivedClass::ScheduleFromName( const char *pName )\ #define IMPLEMENT_CUSTOM_SCHEDULES(derivedClass, baseClass)\
{\ Schedule_t *derivedClass::ScheduleFromName( const char *pName )\
Schedule_t *pSchedule = ScheduleInList( pName, m_scheduleList, ARRAYSIZE(m_scheduleList) );\ {\
if ( !pSchedule )\ Schedule_t *pSchedule = ScheduleInList( pName, m_scheduleList, ARRAYSIZE(m_scheduleList) );\
return baseClass::ScheduleFromName(pName);\ if ( !pSchedule )\
return pSchedule;\ return baseClass::ScheduleFromName(pName);\
} return pSchedule;\
}
#endif //MONSTERS_H
#endif //MONSTERS_H

View File

@@ -1,214 +1,214 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* This source code contains proprietary and confidential information of * This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to * Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access, * persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal. * use or distribution of this code by or to any unlicensed person is illegal.
* *
****/ ****/
//========================================================= //=========================================================
// monsterstate.cpp - base class monster functions for // monsterstate.cpp - base class monster functions for
// controlling core AI. // controlling core AI.
//========================================================= //=========================================================
#include "extdll.h" #include "extdll.h"
#include "util.h" #include "util.h"
#include "cmbase.h" #include "cmbase.h"
#include "cmbasemonster.h" #include "cmbasemonster.h"
#include "nodes.h" #include "nodes.h"
#include "monsters.h" #include "monsters.h"
#include "animation.h" #include "animation.h"
//========================================================= //=========================================================
// SetState // SetState
//========================================================= //=========================================================
void CMBaseMonster :: SetState ( MONSTERSTATE State ) void CMBaseMonster :: SetState ( MONSTERSTATE State )
{ {
/* /*
if ( State != m_MonsterState ) if ( State != m_MonsterState )
{ {
ALERT ( at_aiconsole, "State Changed to %d\n", State ); ALERT ( at_aiconsole, "State Changed to %d\n", State );
} }
*/ */
switch( State ) switch( State )
{ {
// Drop enemy pointers when going to idle // Drop enemy pointers when going to idle
case MONSTERSTATE_IDLE: case MONSTERSTATE_IDLE:
if (( m_hEnemy != NULL ) && if (( m_hEnemy != NULL ) &&
( strcmp(STRING(pev->model), "models/scientist.mdl") != 0)) ( strcmp(STRING(pev->model), "models/scientist.mdl") != 0))
{ {
m_hEnemy = NULL;// not allowed to have an enemy anymore. m_hEnemy = NULL;// not allowed to have an enemy anymore.
ALERT ( at_aiconsole, "Stripped\n" ); ALERT ( at_aiconsole, "Stripped\n" );
} }
break; break;
} }
m_MonsterState = State; m_MonsterState = State;
m_IdealMonsterState = State; m_IdealMonsterState = State;
} }
//========================================================= //=========================================================
// RunAI // RunAI
//========================================================= //=========================================================
void CMBaseMonster :: RunAI ( void ) void CMBaseMonster :: RunAI ( void )
{ {
// to test model's eye height // to test model's eye height
//UTIL_ParticleEffect ( pev->origin + pev->view_ofs, g_vecZero, 255, 10 ); //UTIL_ParticleEffect ( pev->origin + pev->view_ofs, g_vecZero, 255, 10 );
// IDLE sound permitted in ALERT state is because monsters were silent in ALERT state. Only play IDLE sound in IDLE state // IDLE sound permitted in ALERT state is because monsters were silent in ALERT state. Only play IDLE sound in IDLE state
// once we have sounds for that state. // once we have sounds for that state.
if ( ( m_MonsterState == MONSTERSTATE_IDLE || m_MonsterState == MONSTERSTATE_ALERT ) && RANDOM_LONG(0,99) == 0 && !(pev->flags & SF_MONSTER_GAG) ) if ( ( m_MonsterState == MONSTERSTATE_IDLE || m_MonsterState == MONSTERSTATE_ALERT ) && RANDOM_LONG(0,99) == 0 && !(pev->flags & SF_MONSTER_GAG) )
{ {
IdleSound(); IdleSound();
} }
if ( m_MonsterState != MONSTERSTATE_NONE && if ( m_MonsterState != MONSTERSTATE_NONE &&
m_MonsterState != MONSTERSTATE_PRONE && m_MonsterState != MONSTERSTATE_PRONE &&
m_MonsterState != MONSTERSTATE_DEAD )// don't bother with this crap if monster is prone. m_MonsterState != MONSTERSTATE_DEAD )// don't bother with this crap if monster is prone.
{ {
// collect some sensory Condition information. // collect some sensory Condition information.
// don't let monsters outside of the player's PVS act up, or most of the interesting // don't let monsters outside of the player's PVS act up, or most of the interesting
// things will happen before the player gets there! // things will happen before the player gets there!
// UPDATE: We now let COMBAT state monsters think and act fully outside of player PVS. This allows the player to leave // UPDATE: We now let COMBAT state monsters think and act fully outside of player PVS. This allows the player to leave
// an area where monsters are fighting, and the fight will continue. // an area where monsters are fighting, and the fight will continue.
if ( !FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) || ( m_MonsterState == MONSTERSTATE_COMBAT ) ) if ( !FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) || ( m_MonsterState == MONSTERSTATE_COMBAT ) )
{ {
Look( m_flDistLook ); Look( m_flDistLook );
//jlb Listen();// check for audible sounds. //jlb Listen();// check for audible sounds.
// now filter conditions. // now filter conditions.
ClearConditions( IgnoreConditions() ); ClearConditions( IgnoreConditions() );
GetEnemy(); GetEnemy();
} }
// do these calculations if monster has an enemy. // do these calculations if monster has an enemy.
if ( m_hEnemy != NULL ) if ( m_hEnemy != NULL )
{ {
CheckEnemy( m_hEnemy ); CheckEnemy( m_hEnemy );
} }
CheckAmmo(); CheckAmmo();
} }
FCheckAITrigger(); FCheckAITrigger();
PrescheduleThink(); PrescheduleThink();
MaintainSchedule(); MaintainSchedule();
// if the monster didn't use these conditions during the above call to MaintainSchedule() or CheckAITrigger() // if the monster didn't use these conditions during the above call to MaintainSchedule() or CheckAITrigger()
// we throw them out cause we don't want them sitting around through the lifespan of a schedule // we throw them out cause we don't want them sitting around through the lifespan of a schedule
// that doesn't use them. // that doesn't use them.
m_afConditions &= ~( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE ); m_afConditions &= ~( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE );
} }
//========================================================= //=========================================================
// GetIdealState - surveys the Conditions information available // GetIdealState - surveys the Conditions information available
// and finds the best new state for a monster. // and finds the best new state for a monster.
//========================================================= //=========================================================
MONSTERSTATE CMBaseMonster :: GetIdealState ( void ) MONSTERSTATE CMBaseMonster :: GetIdealState ( void )
{ {
int iConditions; int iConditions;
iConditions = IScheduleFlags(); iConditions = IScheduleFlags();
// If no schedule conditions, the new ideal state is probably the reason we're in here. // If no schedule conditions, the new ideal state is probably the reason we're in here.
switch ( m_MonsterState ) switch ( m_MonsterState )
{ {
case MONSTERSTATE_IDLE: case MONSTERSTATE_IDLE:
/* /*
IDLE goes to ALERT upon hearing a sound IDLE goes to ALERT upon hearing a sound
-IDLE goes to ALERT upon being injured -IDLE goes to ALERT upon being injured
IDLE goes to ALERT upon seeing food IDLE goes to ALERT upon seeing food
-IDLE goes to COMBAT upon sighting an enemy -IDLE goes to COMBAT upon sighting an enemy
IDLE goes to HUNT upon smelling food IDLE goes to HUNT upon smelling food
*/ */
{ {
if ( iConditions & bits_COND_NEW_ENEMY ) if ( iConditions & bits_COND_NEW_ENEMY )
{ {
// new enemy! This means an idle monster has seen someone it dislikes, or // new enemy! This means an idle monster has seen someone it dislikes, or
// that a monster in combat has found a more suitable target to attack // that a monster in combat has found a more suitable target to attack
m_IdealMonsterState = MONSTERSTATE_COMBAT; m_IdealMonsterState = MONSTERSTATE_COMBAT;
} }
else if ( iConditions & bits_COND_LIGHT_DAMAGE ) else if ( iConditions & bits_COND_LIGHT_DAMAGE )
{ {
MakeIdealYaw ( m_vecEnemyLKP ); MakeIdealYaw ( m_vecEnemyLKP );
m_IdealMonsterState = MONSTERSTATE_ALERT; m_IdealMonsterState = MONSTERSTATE_ALERT;
} }
else if ( iConditions & bits_COND_HEAVY_DAMAGE ) else if ( iConditions & bits_COND_HEAVY_DAMAGE )
{ {
MakeIdealYaw ( m_vecEnemyLKP ); MakeIdealYaw ( m_vecEnemyLKP );
m_IdealMonsterState = MONSTERSTATE_ALERT; m_IdealMonsterState = MONSTERSTATE_ALERT;
} }
else if ( iConditions & bits_COND_HEAR_SOUND ) else if ( iConditions & bits_COND_HEAR_SOUND )
{ {
} }
else if ( iConditions & (bits_COND_SMELL | bits_COND_SMELL_FOOD) ) else if ( iConditions & (bits_COND_SMELL | bits_COND_SMELL_FOOD) )
{ {
m_IdealMonsterState = MONSTERSTATE_ALERT; m_IdealMonsterState = MONSTERSTATE_ALERT;
} }
break; break;
} }
case MONSTERSTATE_ALERT: case MONSTERSTATE_ALERT:
/* /*
ALERT goes to IDLE upon becoming bored ALERT goes to IDLE upon becoming bored
-ALERT goes to COMBAT upon sighting an enemy -ALERT goes to COMBAT upon sighting an enemy
ALERT goes to HUNT upon hearing a noise ALERT goes to HUNT upon hearing a noise
*/ */
{ {
if ( iConditions & (bits_COND_NEW_ENEMY|bits_COND_SEE_ENEMY) ) if ( iConditions & (bits_COND_NEW_ENEMY|bits_COND_SEE_ENEMY) )
{ {
// see an enemy we MUST attack // see an enemy we MUST attack
m_IdealMonsterState = MONSTERSTATE_COMBAT; m_IdealMonsterState = MONSTERSTATE_COMBAT;
} }
else if ( iConditions & bits_COND_HEAR_SOUND ) else if ( iConditions & bits_COND_HEAR_SOUND )
{ {
m_IdealMonsterState = MONSTERSTATE_ALERT; m_IdealMonsterState = MONSTERSTATE_ALERT;
} }
break; break;
} }
case MONSTERSTATE_COMBAT: case MONSTERSTATE_COMBAT:
/* /*
COMBAT goes to HUNT upon losing sight of enemy COMBAT goes to HUNT upon losing sight of enemy
COMBAT goes to ALERT upon death of enemy COMBAT goes to ALERT upon death of enemy
*/ */
{ {
if ( m_hEnemy == NULL ) if ( m_hEnemy == NULL )
{ {
m_IdealMonsterState = MONSTERSTATE_ALERT; m_IdealMonsterState = MONSTERSTATE_ALERT;
// pev->effects = EF_BRIGHTFIELD; // pev->effects = EF_BRIGHTFIELD;
ALERT ( at_aiconsole, "***Combat state with no enemy!\n" ); ALERT ( at_aiconsole, "***Combat state with no enemy!\n" );
} }
break; break;
} }
case MONSTERSTATE_HUNT: case MONSTERSTATE_HUNT:
/* /*
HUNT goes to ALERT upon seeing food HUNT goes to ALERT upon seeing food
HUNT goes to ALERT upon being injured HUNT goes to ALERT upon being injured
HUNT goes to IDLE if goal touched HUNT goes to IDLE if goal touched
HUNT goes to COMBAT upon seeing enemy HUNT goes to COMBAT upon seeing enemy
*/ */
{ {
break; break;
} }
case MONSTERSTATE_DEAD: case MONSTERSTATE_DEAD:
m_IdealMonsterState = MONSTERSTATE_DEAD; m_IdealMonsterState = MONSTERSTATE_DEAD;
break; break;
} }
return m_IdealMonsterState; return m_IdealMonsterState;
} }

61
src/dlls/music.cpp Normal file
View File

@@ -0,0 +1,61 @@
//=========================================================
// Ambient Music - when triggered, it will play an mp3
// music file locally to players, looped or once.
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbaseextra.h"
// spawnflags
#define SF_MUSIC_LOOP 2 // music will loop instead of playing once.
#define SF_MUSIC_ACTIVATOR_ONLY 4 // only play to the one that activates this entity.
void CMAmbientMusic::KeyValue(KeyValueData *pkvd)
{
CMBaseMonster::KeyValue(pkvd);
}
void CMAmbientMusic::Spawn()
{
pev->solid = SOLID_NOT;
SetUse(&CMAmbientMusic::MusicUse);
pev->classname = MAKE_STRING("ambient_music");
}
void CMAmbientMusic::MusicUse(edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value)
{
// no music
if (FStringNull(pev->message))
return;
// not a player (if not to everyone)
if (pev->spawnflags & SF_MUSIC_ACTIVATOR_ONLY && !UTIL_IsPlayer(pActivator))
return;
if (pev->spawnflags & SF_MUSIC_ACTIVATOR_ONLY)
MESSAGE_BEGIN(MSG_ONE, SVC_STUFFTEXT, NULL, pActivator);
else
MESSAGE_BEGIN(MSG_ALL, SVC_STUFFTEXT);
// triggering off
if (useType == USE_OFF || m_fPlaying && useType != USE_ON)
{
WRITE_STRING("mp3 stop\n");
m_fPlaying = FALSE;
}
else // USE_ON / USE_TOGGLE
{
char szPath[256];
if (pev->spawnflags & SF_MUSIC_LOOP)
sprintf(szPath, "mp3 loop %s\n", STRING(pev->message));
else
sprintf(szPath, "mp3 play %s\n", STRING(pev->message));
WRITE_STRING(szPath);
m_fPlaying = TRUE;
}
MESSAGE_END();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,397 +1,397 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* This source code contains proprietary and confidential information of * This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to * Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access, * persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal. * use or distribution of this code by or to any unlicensed person is illegal.
* *
****/ ****/
//========================================================= //=========================================================
// nodes.h // nodes.h
//========================================================= //=========================================================
//========================================================= //=========================================================
// DEFINE // DEFINE
//========================================================= //=========================================================
#define MAX_STACK_NODES 100 #define MAX_STACK_NODES 100
#define NO_NODE -1 #define NO_NODE -1
#define MAX_NODE_HULLS 4 #define MAX_NODE_HULLS 4
#define bits_NODE_LAND ( 1 << 0 ) // Land node, so nudge if necessary. #define bits_NODE_LAND ( 1 << 0 ) // Land node, so nudge if necessary.
#define bits_NODE_AIR ( 1 << 1 ) // Air node, don't nudge. #define bits_NODE_AIR ( 1 << 1 ) // Air node, don't nudge.
#define bits_NODE_WATER ( 1 << 2 ) // Water node, don't nudge. #define bits_NODE_WATER ( 1 << 2 ) // Water node, don't nudge.
#define bits_NODE_GROUP_REALM (bits_NODE_LAND | bits_NODE_AIR | bits_NODE_WATER) #define bits_NODE_GROUP_REALM (bits_NODE_LAND | bits_NODE_AIR | bits_NODE_WATER)
//========================================================= //=========================================================
// Instance of a node. // Instance of a node.
//========================================================= //=========================================================
class CNode class CNode
{ {
public: public:
Vector m_vecOrigin;// location of this node in space Vector m_vecOrigin;// location of this node in space
Vector m_vecOriginPeek; // location of this node (LAND nodes are NODE_HEIGHT higher). Vector m_vecOriginPeek; // location of this node (LAND nodes are NODE_HEIGHT higher).
BYTE m_Region[3]; // Which of 256 regions do each of the coordinate belong? BYTE m_Region[3]; // Which of 256 regions do each of the coordinate belong?
int m_afNodeInfo;// bits that tell us more about this location int m_afNodeInfo;// bits that tell us more about this location
int m_cNumLinks; // how many links this node has int m_cNumLinks; // how many links this node has
int m_iFirstLink;// index of this node's first link in the link pool. int m_iFirstLink;// index of this node's first link in the link pool.
// Where to start looking in the compressed routing table (offset into m_pRouteInfo). // Where to start looking in the compressed routing table (offset into m_pRouteInfo).
// (4 hull sizes -- smallest to largest + fly/swim), and secondly, door capability. // (4 hull sizes -- smallest to largest + fly/swim), and secondly, door capability.
// //
int m_pNextBestNode[MAX_NODE_HULLS][2]; int m_pNextBestNode[MAX_NODE_HULLS][2];
// Used in finding the shortest path. m_fClosestSoFar is -1 if not visited. // Used in finding the shortest path. m_fClosestSoFar is -1 if not visited.
// Then it is the distance to the source. If another path uses this node // Then it is the distance to the source. If another path uses this node
// and has a closer distance, then m_iPreviousNode is also updated. // and has a closer distance, then m_iPreviousNode is also updated.
// //
float m_flClosestSoFar; // Used in finding the shortest path. float m_flClosestSoFar; // Used in finding the shortest path.
int m_iPreviousNode; int m_iPreviousNode;
short m_sHintType;// there is something interesting in the world at this node's position short m_sHintType;// there is something interesting in the world at this node's position
short m_sHintActivity;// there is something interesting in the world at this node's position short m_sHintActivity;// there is something interesting in the world at this node's position
float m_flHintYaw;// monster on this node should face this yaw to face the hint. float m_flHintYaw;// monster on this node should face this yaw to face the hint.
}; };
//========================================================= //=========================================================
// CLink - A link between 2 nodes // CLink - A link between 2 nodes
//========================================================= //=========================================================
#define bits_LINK_SMALL_HULL ( 1 << 0 )// headcrab box can fit through this connection #define bits_LINK_SMALL_HULL ( 1 << 0 )// headcrab box can fit through this connection
#define bits_LINK_HUMAN_HULL ( 1 << 1 )// player box can fit through this connection #define bits_LINK_HUMAN_HULL ( 1 << 1 )// player box can fit through this connection
#define bits_LINK_LARGE_HULL ( 1 << 2 )// big box can fit through this connection #define bits_LINK_LARGE_HULL ( 1 << 2 )// big box can fit through this connection
#define bits_LINK_FLY_HULL ( 1 << 3 )// a flying big box can fit through this connection #define bits_LINK_FLY_HULL ( 1 << 3 )// a flying big box can fit through this connection
#define bits_LINK_DISABLED ( 1 << 4 )// link is not valid when the set #define bits_LINK_DISABLED ( 1 << 4 )// link is not valid when the set
#define NODE_SMALL_HULL 0 #define NODE_SMALL_HULL 0
#define NODE_HUMAN_HULL 1 #define NODE_HUMAN_HULL 1
#define NODE_LARGE_HULL 2 #define NODE_LARGE_HULL 2
#define NODE_FLY_HULL 3 #define NODE_FLY_HULL 3
class CLink class CLink
{ {
public: public:
int m_iSrcNode;// the node that 'owns' this link ( keeps us from having to make reverse lookups ) int m_iSrcNode;// the node that 'owns' this link ( keeps us from having to make reverse lookups )
int m_iDestNode;// the node on the other end of the link. int m_iDestNode;// the node on the other end of the link.
entvars_t *m_pLinkEnt;// the entity that blocks this connection (doors, etc) entvars_t *m_pLinkEnt;// the entity that blocks this connection (doors, etc)
// m_szLinkEntModelname is not necessarily NULL terminated (so we can store it in a more alignment-friendly 4 bytes) // m_szLinkEntModelname is not necessarily NULL terminated (so we can store it in a more alignment-friendly 4 bytes)
char m_szLinkEntModelname[ 4 ];// the unique name of the brush model that blocks the connection (this is kept for save/restore) char m_szLinkEntModelname[ 4 ];// the unique name of the brush model that blocks the connection (this is kept for save/restore)
int m_afLinkInfo;// information about this link int m_afLinkInfo;// information about this link
float m_flWeight;// length of the link line segment float m_flWeight;// length of the link line segment
}; };
typedef struct typedef struct
{ {
int m_SortedBy[3]; int m_SortedBy[3];
int m_CheckedEvent; int m_CheckedEvent;
} DIST_INFO; } DIST_INFO;
typedef struct typedef struct
{ {
Vector v; Vector v;
short n; // Nearest node or -1 if no node found. short n; // Nearest node or -1 if no node found.
} CACHE_ENTRY; } CACHE_ENTRY;
//========================================================= //=========================================================
// CGraph // CGraph
//========================================================= //=========================================================
#define GRAPH_VERSION (int)16// !!!increment this whever graph/node/link classes change, to obsolesce older disk files. #define GRAPH_VERSION (int)16// !!!increment this whever graph/node/link classes change, to obsolesce older disk files.
class CGraph class CGraph
{ {
public: public:
// the graph has two flags, and should not be accessed unless both flags are TRUE! // the graph has two flags, and should not be accessed unless both flags are TRUE!
BOOL m_fGraphPresent;// is the graph in memory? BOOL m_fGraphPresent;// is the graph in memory?
BOOL m_fGraphPointersSet;// are the entity pointers for the graph all set? BOOL m_fGraphPointersSet;// are the entity pointers for the graph all set?
BOOL m_fRoutingComplete; // are the optimal routes computed, yet? BOOL m_fRoutingComplete; // are the optimal routes computed, yet?
CNode *m_pNodes;// pointer to the memory block that contains all node info CNode *m_pNodes;// pointer to the memory block that contains all node info
CLink *m_pLinkPool;// big list of all node connections CLink *m_pLinkPool;// big list of all node connections
char *m_pRouteInfo; // compressed routing information the nodes use. char *m_pRouteInfo; // compressed routing information the nodes use.
int m_cNodes;// total number of nodes int m_cNodes;// total number of nodes
int m_cLinks;// total number of links int m_cLinks;// total number of links
int m_nRouteInfo; // size of m_pRouteInfo in bytes. int m_nRouteInfo; // size of m_pRouteInfo in bytes.
// Tables for making nearest node lookup faster. SortedBy provided nodes in a // Tables for making nearest node lookup faster. SortedBy provided nodes in a
// order of a particular coordinate. Instead of doing a binary search, RangeStart // order of a particular coordinate. Instead of doing a binary search, RangeStart
// and RangeEnd let you get to the part of SortedBy that you are interested in. // and RangeEnd let you get to the part of SortedBy that you are interested in.
// //
// Once you have a point of interest, the only way you'll find a closer point is // Once you have a point of interest, the only way you'll find a closer point is
// if at least one of the coordinates is closer than the ones you have now. So we // if at least one of the coordinates is closer than the ones you have now. So we
// search each range. After the search is exhausted, we know we have the closest // search each range. After the search is exhausted, we know we have the closest
// node. // node.
// //
#define CACHE_SIZE 128 #define CACHE_SIZE 128
#define NUM_RANGES 256 #define NUM_RANGES 256
DIST_INFO *m_di; // This is m_cNodes long, but the entries don't correspond to CNode entries. DIST_INFO *m_di; // This is m_cNodes long, but the entries don't correspond to CNode entries.
int m_RangeStart[3][NUM_RANGES]; int m_RangeStart[3][NUM_RANGES];
int m_RangeEnd[3][NUM_RANGES]; int m_RangeEnd[3][NUM_RANGES];
float m_flShortest; float m_flShortest;
int m_iNearest; int m_iNearest;
int m_minX, m_minY, m_minZ, m_maxX, m_maxY, m_maxZ; int m_minX, m_minY, m_minZ, m_maxX, m_maxY, m_maxZ;
int m_minBoxX, m_minBoxY, m_minBoxZ, m_maxBoxX, m_maxBoxY, m_maxBoxZ; int m_minBoxX, m_minBoxY, m_minBoxZ, m_maxBoxX, m_maxBoxY, m_maxBoxZ;
int m_CheckedCounter; int m_CheckedCounter;
float m_RegionMin[3], m_RegionMax[3]; // The range of nodes. float m_RegionMin[3], m_RegionMax[3]; // The range of nodes.
CACHE_ENTRY m_Cache[CACHE_SIZE]; CACHE_ENTRY m_Cache[CACHE_SIZE];
int m_HashPrimes[16]; int m_HashPrimes[16];
short *m_pHashLinks; short *m_pHashLinks;
int m_nHashLinks; int m_nHashLinks;
// kinda sleazy. In order to allow variety in active idles for monster groups in a room with more than one node, // kinda sleazy. In order to allow variety in active idles for monster groups in a room with more than one node,
// we keep track of the last node we searched from and store it here. Subsequent searches by other monsters will pick // we keep track of the last node we searched from and store it here. Subsequent searches by other monsters will pick
// up where the last search stopped. // up where the last search stopped.
int m_iLastActiveIdleSearch; int m_iLastActiveIdleSearch;
// another such system used to track the search for cover nodes, helps greatly with two monsters trying to get to the same node. // another such system used to track the search for cover nodes, helps greatly with two monsters trying to get to the same node.
int m_iLastCoverSearch; int m_iLastCoverSearch;
// functions to create the graph // functions to create the graph
int LinkVisibleNodes ( CLink *pLinkPool, FILE *file, int *piBadNode ); int LinkVisibleNodes ( CLink *pLinkPool, FILE *file, int *piBadNode );
int RejectInlineLinks ( CLink *pLinkPool, FILE *file ); int RejectInlineLinks ( CLink *pLinkPool, FILE *file );
int FindShortestPath ( int *piPath, int iStart, int iDest, int iHull, int afCapMask); int FindShortestPath ( int *piPath, int iStart, int iDest, int iHull, int afCapMask);
int FindNearestNode ( const Vector &vecOrigin, CMBaseEntity *pEntity ); int FindNearestNode ( const Vector &vecOrigin, CMBaseEntity *pEntity );
int FindNearestNode ( const Vector &vecOrigin, int afNodeTypes ); int FindNearestNode ( const Vector &vecOrigin, int afNodeTypes );
//int FindNearestLink ( const Vector &vecTestPoint, int *piNearestLink, BOOL *pfAlongLine ); //int FindNearestLink ( const Vector &vecTestPoint, int *piNearestLink, BOOL *pfAlongLine );
float PathLength( int iStart, int iDest, int iHull, int afCapMask ); float PathLength( int iStart, int iDest, int iHull, int afCapMask );
int NextNodeInRoute( int iCurrentNode, int iDest, int iHull, int iCap ); int NextNodeInRoute( int iCurrentNode, int iDest, int iHull, int iCap );
enum NODEQUERY { NODEGRAPH_DYNAMIC, NODEGRAPH_STATIC }; enum NODEQUERY { NODEGRAPH_DYNAMIC, NODEGRAPH_STATIC };
// A static query means we're asking about the possiblity of handling this entity at ANY time // A static query means we're asking about the possiblity of handling this entity at ANY time
// A dynamic query means we're asking about it RIGHT NOW. So we should query the current state // A dynamic query means we're asking about it RIGHT NOW. So we should query the current state
int HandleLinkEnt ( int iNode, entvars_t *pevLinkEnt, int afCapMask, NODEQUERY queryType ); int HandleLinkEnt ( int iNode, entvars_t *pevLinkEnt, int afCapMask, NODEQUERY queryType );
entvars_t* LinkEntForLink ( CLink *pLink, CNode *pNode ); entvars_t* LinkEntForLink ( CLink *pLink, CNode *pNode );
void ShowNodeConnections ( int iNode ); void ShowNodeConnections ( int iNode );
void InitGraph( void ); void InitGraph( void );
int AllocNodes ( void ); int AllocNodes ( void );
int CheckNODFile(char *szMapName); int CheckNODFile(char *szMapName);
int FLoadGraph(char *szMapName); int FLoadGraph(char *szMapName);
int FSaveGraph(char *szMapName); int FSaveGraph(char *szMapName);
int FSetGraphPointers(void); int FSetGraphPointers(void);
void CheckNode(Vector vecOrigin, int iNode); void CheckNode(Vector vecOrigin, int iNode);
void BuildRegionTables(void); void BuildRegionTables(void);
void ComputeStaticRoutingTables(void); void ComputeStaticRoutingTables(void);
void TestRoutingTables(void); void TestRoutingTables(void);
void HashInsert(int iSrcNode, int iDestNode, int iKey); void HashInsert(int iSrcNode, int iDestNode, int iKey);
void HashSearch(int iSrcNode, int iDestNode, int &iKey); void HashSearch(int iSrcNode, int iDestNode, int &iKey);
void HashChoosePrimes(int TableSize); void HashChoosePrimes(int TableSize);
void BuildLinkLookups(void); void BuildLinkLookups(void);
void SortNodes(void); void SortNodes(void);
int HullIndex( const CMBaseEntity *pEntity ); // what hull the monster uses int HullIndex( const CMBaseEntity *pEntity ); // what hull the monster uses
int NodeType( const CMBaseEntity *pEntity ); // what node type the monster uses int NodeType( const CMBaseEntity *pEntity ); // what node type the monster uses
inline int CapIndex( int afCapMask ) inline int CapIndex( int afCapMask )
{ {
if (afCapMask & (bits_CAP_OPEN_DOORS | bits_CAP_AUTO_DOORS | bits_CAP_USE)) if (afCapMask & (bits_CAP_OPEN_DOORS | bits_CAP_AUTO_DOORS | bits_CAP_USE))
return 1; return 1;
return 0; return 0;
} }
inline CNode &Node( int i ) inline CNode &Node( int i )
{ {
#ifdef _DEBUG #ifdef _DEBUG
if ( !m_pNodes || i < 0 || i > m_cNodes ) if ( !m_pNodes || i < 0 || i > m_cNodes )
ALERT( at_error, "Bad Node!\n" ); ALERT( at_error, "Bad Node!\n" );
#endif #endif
return m_pNodes[i]; return m_pNodes[i];
} }
inline CLink &Link( int i ) inline CLink &Link( int i )
{ {
#ifdef _DEBUG #ifdef _DEBUG
if ( !m_pLinkPool || i < 0 || i > m_cLinks ) if ( !m_pLinkPool || i < 0 || i > m_cLinks )
ALERT( at_error, "Bad link!\n" ); ALERT( at_error, "Bad link!\n" );
#endif #endif
return m_pLinkPool[i]; return m_pLinkPool[i];
} }
inline CLink &NodeLink( int iNode, int iLink ) inline CLink &NodeLink( int iNode, int iLink )
{ {
return Link( Node( iNode ).m_iFirstLink + iLink ); return Link( Node( iNode ).m_iFirstLink + iLink );
} }
inline CLink &NodeLink( const CNode &node, int iLink ) inline CLink &NodeLink( const CNode &node, int iLink )
{ {
return Link( node.m_iFirstLink + iLink ); return Link( node.m_iFirstLink + iLink );
} }
inline int INodeLink ( int iNode, int iLink ) inline int INodeLink ( int iNode, int iLink )
{ {
return NodeLink( iNode, iLink ).m_iDestNode; return NodeLink( iNode, iLink ).m_iDestNode;
} }
#if 0 #if 0
inline CNode &SourceNode( int iNode, int iLink ) inline CNode &SourceNode( int iNode, int iLink )
{ {
return Node( NodeLink( iNode, iLink ).m_iSrcNode ); return Node( NodeLink( iNode, iLink ).m_iSrcNode );
} }
inline CNode &DestNode( int iNode, int iLink ) inline CNode &DestNode( int iNode, int iLink )
{ {
return Node( NodeLink( iNode, iLink ).m_iDestNode ); return Node( NodeLink( iNode, iLink ).m_iDestNode );
} }
inline CNode *PNodeLink ( int iNode, int iLink ) inline CNode *PNodeLink ( int iNode, int iLink )
{ {
return &DestNode( iNode, iLink ); return &DestNode( iNode, iLink );
} }
#endif #endif
}; };
//========================================================= //=========================================================
// Nodes start out as ents in the level. The node graph // Nodes start out as ents in the level. The node graph
// is built, then these ents are discarded. // is built, then these ents are discarded.
//========================================================= //=========================================================
class CNodeEnt : public CMBaseEntity class CNodeEnt : public CMBaseEntity
{ {
void Spawn( void ); void Spawn( void );
void KeyValue( KeyValueData *pkvd ); void KeyValue( KeyValueData *pkvd );
virtual int ObjectCaps( void ) { return CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } virtual int ObjectCaps( void ) { return CMBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
short m_sHintType; short m_sHintType;
short m_sHintActivity; short m_sHintActivity;
}; };
//========================================================= //=========================================================
// Node viewer // Node viewer
//========================================================= //=========================================================
class CNodeViewer : public CMBaseEntity class CNodeViewer : public CMBaseEntity
{ {
public: public:
void Spawn( void ); void Spawn( void );
int m_iBaseNode; int m_iBaseNode;
int m_iDraw; int m_iDraw;
int m_nVisited; int m_nVisited;
int m_aFrom[128]; int m_aFrom[128];
int m_aTo[128]; int m_aTo[128];
int m_iHull; int m_iHull;
int m_afNodeType; int m_afNodeType;
Vector m_vecColor; Vector m_vecColor;
void FindNodeConnections( int iNode ); void FindNodeConnections( int iNode );
void AddNode( int iFrom, int iTo ); void AddNode( int iFrom, int iTo );
void EXPORT DrawThink( void ); void EXPORT DrawThink( void );
}; };
//========================================================= //=========================================================
// CStack - last in, first out. // CStack - last in, first out.
//========================================================= //=========================================================
class CStack class CStack
{ {
public: public:
CStack( void ); CStack( void );
void Push( int value ); void Push( int value );
int Pop( void ); int Pop( void );
int Top( void ); int Top( void );
int Empty( void ) { return m_level==0; } int Empty( void ) { return m_level==0; }
int Size( void ) { return m_level; } int Size( void ) { return m_level; }
void CopyToArray ( int *piArray ); void CopyToArray ( int *piArray );
private: private:
int m_stack[ MAX_STACK_NODES ]; int m_stack[ MAX_STACK_NODES ];
int m_level; int m_level;
}; };
//========================================================= //=========================================================
// CQueue - first in, first out. // CQueue - first in, first out.
//========================================================= //=========================================================
class CQueue class CQueue
{ {
public: public:
CQueue( void );// constructor CQueue( void );// constructor
inline int Full ( void ) { return ( m_cSize == MAX_STACK_NODES ); } inline int Full ( void ) { return ( m_cSize == MAX_STACK_NODES ); }
inline int Empty ( void ) { return ( m_cSize == 0 ); } inline int Empty ( void ) { return ( m_cSize == 0 ); }
//inline int Tail ( void ) { return ( m_queue[ m_tail ] ); } //inline int Tail ( void ) { return ( m_queue[ m_tail ] ); }
inline int Size ( void ) { return ( m_cSize ); } inline int Size ( void ) { return ( m_cSize ); }
void Insert( int, float ); void Insert( int, float );
int Remove( float & ); int Remove( float & );
private: private:
int m_cSize; int m_cSize;
struct tag_QUEUE_NODE struct tag_QUEUE_NODE
{ {
int Id; int Id;
float Priority; float Priority;
} m_queue[ MAX_STACK_NODES ]; } m_queue[ MAX_STACK_NODES ];
int m_head; int m_head;
int m_tail; int m_tail;
}; };
//========================================================= //=========================================================
// CQueuePriority - Priority queue (smallest item out first). // CQueuePriority - Priority queue (smallest item out first).
// //
//========================================================= //=========================================================
class CQueuePriority class CQueuePriority
{ {
public: public:
CQueuePriority( void );// constructor CQueuePriority( void );// constructor
inline int Full ( void ) { return ( m_cSize == MAX_STACK_NODES ); } inline int Full ( void ) { return ( m_cSize == MAX_STACK_NODES ); }
inline int Empty ( void ) { return ( m_cSize == 0 ); } inline int Empty ( void ) { return ( m_cSize == 0 ); }
//inline int Tail ( float & ) { return ( m_queue[ m_tail ].Id ); } //inline int Tail ( float & ) { return ( m_queue[ m_tail ].Id ); }
inline int Size ( void ) { return ( m_cSize ); } inline int Size ( void ) { return ( m_cSize ); }
void Insert( int, float ); void Insert( int, float );
int Remove( float &); int Remove( float &);
private: private:
int m_cSize; int m_cSize;
struct tag_HEAP_NODE struct tag_HEAP_NODE
{ {
int Id; int Id;
float Priority; float Priority;
} m_heap[ MAX_STACK_NODES ]; } m_heap[ MAX_STACK_NODES ];
void Heap_SiftDown(int); void Heap_SiftDown(int);
void Heap_SiftUp(void); void Heap_SiftUp(void);
}; };
//========================================================= //=========================================================
// hints - these MUST coincide with the HINTS listed under // hints - these MUST coincide with the HINTS listed under
// info_node in the FGD file! // info_node in the FGD file!
//========================================================= //=========================================================
enum enum
{ {
HINT_NONE = 0, HINT_NONE = 0,
HINT_WORLD_DOOR, HINT_WORLD_DOOR,
HINT_WORLD_WINDOW, HINT_WORLD_WINDOW,
HINT_WORLD_BUTTON, HINT_WORLD_BUTTON,
HINT_WORLD_MACHINERY, HINT_WORLD_MACHINERY,
HINT_WORLD_LEDGE, HINT_WORLD_LEDGE,
HINT_WORLD_LIGHT_SOURCE, HINT_WORLD_LIGHT_SOURCE,
HINT_WORLD_HEAT_SOURCE, HINT_WORLD_HEAT_SOURCE,
HINT_WORLD_BLINKING_LIGHT, HINT_WORLD_BLINKING_LIGHT,
HINT_WORLD_BRIGHT_COLORS, HINT_WORLD_BRIGHT_COLORS,
HINT_WORLD_HUMAN_BLOOD, HINT_WORLD_HUMAN_BLOOD,
HINT_WORLD_ALIEN_BLOOD, HINT_WORLD_ALIEN_BLOOD,
HINT_TACTICAL_EXIT = 100, HINT_TACTICAL_EXIT = 100,
HINT_TACTICAL_VANTAGE, HINT_TACTICAL_VANTAGE,
HINT_TACTICAL_AMBUSH, HINT_TACTICAL_AMBUSH,
HINT_STUKA_PERCH = 300, HINT_STUKA_PERCH = 300,
HINT_STUKA_LANDING, HINT_STUKA_LANDING,
}; };
extern CGraph WorldGraph; extern CGraph WorldGraph;

329
src/dlls/otis.cpp Normal file
View File

@@ -0,0 +1,329 @@
// HUGE thanks to DrBeef for his hlsdk-xash3d-opfor repository!
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
//=========================================================
// monster template
//=========================================================
// UNDONE: Holster weapon?
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "defaultai.h"
#include "weapons.h"
#define NUM_OTIS_HEADS 2 // heads available for otis model
#define GUN_GROUP 1
#define HEAD_GROUP 2
#define HEAD_HAIR 0
#define HEAD_BALD 1
#define GUN_NONE 0
#define GUN_EAGLE 1
#define GUN_DONUT 2
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
// first flag is Otis dying for scripted sequences?
#define OTIS_AE_DRAW ( 2 )
#define OTIS_AE_SHOOT ( 3 )
#define OTIS_AE_HOLSTER ( 4 )
#define OTIS_BODY_GUNHOLSTERED 0
#define OTIS_BODY_GUNDRAWN 1
#define OTIS_BODY_DONUT 2
//=========================================================
// ALertSound - otis says "Freeze!"
//=========================================================
void CMOtis::AlertSound(void)
{
if (m_hEnemy != 0)
{
if (FOkToSpeak())
{
PlaySentence("OT_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE);
}
}
}
//=========================================================
// BarneyFirePistol - shoots one round from the pistol at
// the enemy otis is facing.
//=========================================================
void CMOtis::BarneyFirePistol(void)
{
Vector vecShootOrigin;
UTIL_MakeVectors(pev->angles);
vecShootOrigin = pev->origin + Vector(0, 0, 55);
Vector vecShootDir = ShootAtEnemy(vecShootOrigin);
Vector angDir = UTIL_VecToAngles(vecShootDir);
SetBlending(0, angDir.x);
pev->effects = EF_MUZZLEFLASH;
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_357);
int pitchShift = RANDOM_LONG(0, 20);
// Only shift about half the time
if (pitchShift > 10)
pitchShift = 0;
else
pitchShift -= 5;
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "weapons/desert_eagle_fire.wav", 1, ATTN_NORM, 0, 100 + pitchShift);
// UNDONE: Reload?
m_cAmmoLoaded--;// take away a bullet!
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//
// Returns number of events handled, 0 if none.
//=========================================================
void CMOtis::HandleAnimEvent(MonsterEvent_t *pEvent)
{
switch (pEvent->event)
{
case OTIS_AE_SHOOT:
BarneyFirePistol();
break;
case OTIS_AE_DRAW:
// otis' bodygroup switches here so he can pull gun from holster
// pev->body = OTIS_BODY_GUNDRAWN;
SetBodygroup( GUN_GROUP, GUN_EAGLE );
m_fGunDrawn = TRUE;
break;
case OTIS_AE_HOLSTER:
// change bodygroup to replace gun in holster
// pev->body = OTIS_BODY_GUNHOLSTERED;
SetBodygroup( GUN_GROUP, GUN_NONE );
m_fGunDrawn = FALSE;
break;
default:
CMBarney::HandleAnimEvent(pEvent);
}
}
//=========================================================
// Spawn
//=========================================================
void CMOtis::Spawn()
{
Precache();
SET_MODEL(ENT(pev), (!FStringNull( pev->model ) ? STRING( pev->model ) : "models/otis.mdl"));
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = !m_bloodColor ? BLOOD_COLOR_RED : m_bloodColor;
if (!pev->health) { pev->health = gSkillData.otisHealth; }
pev->view_ofs = Vector(0, 0, 50);// position of the eyes relative to monster's origin.
m_flFieldOfView = VIEW_FIELD_WIDE; // NOTE: we need a wide field of view so npc will notice player and say hello
m_MonsterState = MONSTERSTATE_NONE;
pev->body = 0; // gun in holster
m_fGunDrawn = FALSE;
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
// Make sure hands are white.
pev->skin = 0;
// Select a random head.
if (head == -1)
{
SetBodygroup(HEAD_GROUP, RANDOM_LONG(0, NUM_OTIS_HEADS - 1));
}
else
{
SetBodygroup(HEAD_GROUP, head);
}
if (bodystate == -1)
{
SetBodygroup(GUN_GROUP, RANDOM_LONG(OTIS_BODY_GUNHOLSTERED, OTIS_BODY_GUNDRAWN)); // don't random donut
}
else
{
SetBodygroup(GUN_GROUP, bodystate);
}
MonsterInit();
pev->classname = MAKE_STRING( "monster_otis" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Otis" );
}
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CMOtis::Precache()
{
PRECACHE_MODEL("models/otis.mdl");
PRECACHE_SOUND("weapons/desert_eagle_fire.wav");
PRECACHE_SOUND("barney/ba_pain1.wav");
PRECACHE_SOUND("barney/ba_pain2.wav");
PRECACHE_SOUND("barney/ba_pain3.wav");
PRECACHE_SOUND("barney/ba_die1.wav");
PRECACHE_SOUND("barney/ba_die2.wav");
PRECACHE_SOUND("barney/ba_die3.wav");
// every new otis must call this, otherwise
// when a level is loaded, nobody will talk (time is reset to 0)
TalkInit();
CMTalkMonster::Precache();
}
// Init talk data
void CMOtis::TalkInit()
{
CMTalkMonster::TalkInit();
// scientists speach group names (group names are in sentences.txt)
m_szGrp[TLK_ANSWER] = "OT_ANSWER";
m_szGrp[TLK_QUESTION] = "OT_QUESTION";
m_szGrp[TLK_IDLE] = "OT_IDLE";
m_szGrp[TLK_STARE] = "OT_STARE";
m_szGrp[TLK_USE] = "OT_OK";
m_szGrp[TLK_UNUSE] = "OT_WAIT";
m_szGrp[TLK_STOP] = "OT_STOP";
m_szGrp[TLK_NOSHOOT] = "OT_SCARED";
m_szGrp[TLK_HELLO] = "OT_HELLO";
m_szGrp[TLK_PLHURT1] = "!OT_CUREA";
m_szGrp[TLK_PLHURT2] = "!OT_CUREB";
m_szGrp[TLK_PLHURT3] = "!OT_CUREC";
m_szGrp[TLK_PHELLO] = NULL;
m_szGrp[TLK_PIDLE] = NULL;
m_szGrp[TLK_PQUESTION] = NULL;
m_szGrp[TLK_SMELL] = "OT_SMELL";
m_szGrp[TLK_WOUND] = "OT_WOUND";
m_szGrp[TLK_MORTAL] = "OT_MORTAL";
// get voice for head - just one otis voice for now
m_voicePitch = 100;
}
int CMOtis::TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
{
// make sure friends talk about it if player hurts talkmonsters...
int ret = CMTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
if (!IsAlive() || pev->deadflag == DEAD_DYING)
return ret;
if (m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT))
{
// This is a heurstic to determine if the player intended to harm me
// If I have an enemy, we can't establish intent (may just be crossfire)
if ( ( m_hEnemy != NULL ) && UTIL_IsPlayer(m_hEnemy) )
{
Remember( bits_MEMORY_PROVOKED );
}
}
return ret;
}
void CMOtis::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
{
switch (ptr->iHitgroup)
{
case HITGROUP_CHEST:
case HITGROUP_STOMACH:
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
{
flDamage = flDamage / 2;
}
break;
case 10: // Otis wears no helmet, so do not prevent taking headshot damage.
// always a head shot
ptr->iHitgroup = HITGROUP_HEAD;
break;
default:
break;
}
CMTalkMonster::TraceAttack(pevAttacker, flDamage, vecDir, ptr, bitsDamageType);
}
void CMOtis::Killed(entvars_t *pevAttacker, int iGib)
{
if (GetBodygroup(GUN_GROUP) != OTIS_BODY_GUNHOLSTERED)
{
// drop the gun!
SetBodygroup(GUN_GROUP, OTIS_BODY_GUNHOLSTERED);
}
CMTalkMonster::Killed(pevAttacker, iGib);
}
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
//=========================================================
// GetSchedule - Decides which type of schedule best suits
// the monster's current state and conditions. Then calls
// monster's member function to get a pointer to a schedule
// of the proper type.
//=========================================================
Schedule_t *CMOtis::GetSchedule(void)
{
if (HasConditions(bits_COND_ENEMY_DEAD) && FOkToSpeak())
{
PlaySentence("OT_KILL", 4, VOL_NORM, ATTN_NORM);
}
return CMBarney::GetSchedule();
}
void CMOtis::KeyValue(KeyValueData *pkvd)
{
if (FStrEq(pkvd->szKeyName, "head"))
{
head = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CMBarney::KeyValue(pkvd);
}

1072
src/dlls/pitdrone.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,43 +1,43 @@
/*** /***
* *
* Copyright (c) 1996-2001, Valve LLC. All rights reserved. * Copyright (c) 1996-2001, Valve LLC. All rights reserved.
* *
* This product contains software technology licensed from Id * This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved. * All Rights Reserved.
* *
* Use, distribution, and modification of this source code and/or resulting * Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from * object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited * Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC. * without written permission from Valve LLC.
* *
****/ ****/
#ifndef PLANE_H #ifndef PLANE_H
#define PLANE_H #define PLANE_H
//========================================================= //=========================================================
// Plane // Plane
//========================================================= //=========================================================
class CPlane class CPlane
{ {
public: public:
CPlane ( void ); CPlane ( void );
//========================================================= //=========================================================
// InitializePlane - Takes a normal for the plane and a // InitializePlane - Takes a normal for the plane and a
// point on the plane and // point on the plane and
//========================================================= //=========================================================
void InitializePlane ( const Vector &vecNormal, const Vector &vecPoint ); void InitializePlane ( const Vector &vecNormal, const Vector &vecPoint );
//========================================================= //=========================================================
// PointInFront - determines whether the given vector is // PointInFront - determines whether the given vector is
// in front of the plane. // in front of the plane.
//========================================================= //=========================================================
BOOL PointInFront ( const Vector &vecPoint ); BOOL PointInFront ( const Vector &vecPoint );
Vector m_vecNormal; Vector m_vecNormal;
float m_flDist; float m_flDist;
BOOL m_fInitialized; BOOL m_fInitialized;
}; };
#endif // PLANE_H #endif // PLANE_H

423
src/dlls/rgrunt.cpp Normal file
View File

@@ -0,0 +1,423 @@
/***
*
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
//=========================================================
// Robo Grunt
//=========================================================
#include "extdll.h"
#include "plane.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "animation.h"
#include "weapons.h"
#include "cmtalkmonster.h"
#include "effects.h"
#include "explode.h"
#include "customentity.h"
//=========================================================
// monster-specific DEFINE's
//=========================================================
#define RGRUNT_CLIP_SIZE 36 // how many bullets in a clip? - NOTE: 3 round burst sound, so keep as 3 * x!
// Weapon flags
#define RGRUNT_9MMAR (1 << 0)
#define RGRUNT_HANDGRENADE (1 << 1)
#define RGRUNT_GRENADELAUNCHER (1 << 2)
#define RGRUNT_SHOTGUN (1 << 3)
// Body groups
#define GUN_GROUP 2
// Gun values
#define GUN_MP5 0
#define GUN_SHOTGUN 1
#define GUN_NONE 2
// How many sparks to emit when low on health
#define RGRUNT_MAX_SPARKS 5
//=========================================================
// This sound is muted for Robo Grunts
//=========================================================
void CMRGrunt::PainSound(void)
{
}
// This is a gross hack: RGRUNT inherits from HGRUNT, so...
// to avoid duplicating code, I'm going to define it here
// then use it in hgrunt whenever speech is needed. -Giegue
const char *CMRGrunt::pRobotSentences[] =
{
"RB_GREN", // Sven Co-op uses "RB_" for rgrunt sentences
"RB_ALERT",
"RB_MONSTER",
"RB_COVER",
"RB_THROW",
"RB_CHARGE",
"RB_TAUNT",
};
//=========================================================
// DeathSound
//=========================================================
void CMRGrunt::DeathSound(void)
{
switch ( RANDOM_LONG(0,1) )
{
case 0:
EMIT_SOUND( ENT(pev), CHAN_VOICE, "turret/tu_die.wav", 1, ATTN_IDLE );
break;
case 1:
EMIT_SOUND( ENT(pev), CHAN_VOICE, "turret/tu_die2.wav", 1, ATTN_IDLE );
break;
}
// Use this spot to activate the explosion
int duration = RANDOM_LONG( 3, 9 );
/* Smoke effect */
// variable smoke balls
// 1.7X normal size
// 0 radial distribution
// instant start
SmokeCreate( pev->origin, duration * 7, 17, 0, 0 );
// "Gib"
pev->nextthink = gpGlobals->time + duration;
SetThink( &CMRGrunt::StartGib );
}
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CMRGrunt::Classify(void)
{
if ( m_iClassifyOverride == -1 ) // helper
return CLASS_NONE;
else if ( m_iClassifyOverride > 0 )
return m_iClassifyOverride; // override
return CLASS_HUMAN_MILITARY;
}
//=========================================================
// Killed - Explode a few seconds after death
//=========================================================
void CMRGrunt::Killed(entvars_t *pevAttacker, int iGib)
{
// Turn off electricity
if ( m_flActiveDischarge != 0 )
{
pev->renderfx = kRenderFxNone;
m_flActiveDischarge = 0;
}
// Disallow this monster to fade away, need to keep it around for the explosion
pev->owner = 0;
pev->spawnflags &= ~SF_MONSTER_FADECORPSE;
pev->solid = SOLID_NOT; // stop interacting with the world
CMBaseMonster::Killed(pevAttacker, iGib);
}
void CMRGrunt::StartGib(void)
{
// derp
GibMonster();
}
//=========================================================
// GibMonster - Boom!
//=========================================================
void CMRGrunt::GibMonster()
{
// Don't call this more times than needed
if ( pev->iuser1 != 0 )
return;
pev->iuser1 = 1;
Vector vecSpot = pev->origin + (pev->mins + pev->maxs) * 0.5;
// Explosion
ExplosionCreate( vecSpot, g_vecZero, ENT(pev), 128, 0, 0 );
// Wreckage
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, vecSpot );
WRITE_BYTE( TE_BREAKMODEL );
// position
WRITE_COORD( vecSpot.x );
WRITE_COORD( vecSpot.y );
WRITE_COORD( vecSpot.z );
// size
WRITE_COORD( 96 );
WRITE_COORD( 96 );
WRITE_COORD( 16 );
// velocity
WRITE_COORD( 0 );
WRITE_COORD( 0 );
WRITE_COORD( 30 );
// randomization
WRITE_BYTE( 15 );
// Model
WRITE_SHORT( m_iBodyGibs ); //model id#
// # of shards
WRITE_BYTE( 35 );
// duration
WRITE_BYTE( 100 );// 5.0 seconds
// flags
WRITE_BYTE( BREAK_METAL );
MESSAGE_END();
SetThink( &CMBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time;
}
//=========================================================
// RunAI - Robo Grunt emits sparks when its low on health.
//=========================================================
void CMRGrunt::RunAI(void)
{
CMBaseMonster::RunAI();
if ( pev->health <= ( pev->max_health / 10 ) ) // below 10% health
{
// Spark ON
if ( gpGlobals->time > m_flNextSpark )
{
// Code looks familiar? It's CBaseButton::DoSpark
for ( int spark_num = 0; spark_num < RGRUNT_MAX_SPARKS; spark_num++ )
{
Vector tmp = pev->origin + (pev->mins + pev->maxs) * 0.5; // grab center
tmp.x += RANDOM_FLOAT( -( pev->size.x / 2 ), pev->size.x / 2); // then randomize
tmp.y += RANDOM_FLOAT( -( pev->size.y / 2 ), pev->size.y / 2);
tmp.z += RANDOM_FLOAT( -( pev->size.z / 2 ), pev->size.z / 2);
UTIL_Sparks( tmp );
}
switch ( (int)(RANDOM_FLOAT(0,1) * 6) )
{
case 0: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark1.wav", 0.6, ATTN_NORM); break;
case 1: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark2.wav", 0.6, ATTN_NORM); break;
case 2: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark3.wav", 0.6, ATTN_NORM); break;
case 3: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark4.wav", 0.6, ATTN_NORM); break;
case 4: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark5.wav", 0.6, ATTN_NORM); break;
case 5: EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark6.wav", 0.6, ATTN_NORM); break;
}
m_flNextSpark = gpGlobals->time + 0.5;
}
// Glow/Hurt ON
if ( gpGlobals->time > m_flNextDischarge )
{
// Turn on the electric glow
pev->renderfx = kRenderFxGlowShell;
pev->rendercolor = Vector( 100, 150, 250 ); // r, g, b
EMIT_SOUND(ENT(pev), CHAN_BODY, "debris/beamstart14.wav", 0.8, ATTN_NORM);
// Sustain the electricity for this long
m_flActiveDischarge = gpGlobals->time + RANDOM_FLOAT( 0.3, 0.6 );
// Discharge again in...
m_flNextDischarge = gpGlobals->time + RANDOM_FLOAT( 0.9, 2.7 );
}
// Glow/Hurt OFF
if ( gpGlobals->time > m_flActiveDischarge )
{
// Turn off electricity
pev->renderfx = kRenderFxNone;
m_flActiveDischarge = 0;
}
}
}
//=========================================================
// SparkTouch - Hurt players who come too close to it
//=========================================================
void CMRGrunt::SparkTouch( edict_t *pOther )
{
// No electricity, no harm
if ( m_flActiveDischarge == 0 )
return;
// Only affect players
if ( UTIL_IsPlayer( pOther ) )
{
// Because of Touch(), players are going to be hurt every server frame.
// Don't be bullshit like Sven Co-op, set the damage REALLY LOW.
UTIL_TakeDamage( pOther, pev, pev, 1, DMG_SHOCK );
}
}
//=========================================================
// TraceAttack - Override for robo grunt
// Emit ricochet sparks if getting hurt from bullets
//=========================================================
void CMRGrunt::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType )
{
// Absorb damage and emit ricochet if bullets or melee attacks are used
if ( bitsDamageType & ( DMG_BULLET | DMG_SLASH | DMG_CLUB ) )
{
if ( RANDOM_LONG( 0, 100 ) < 20 )
{
UTIL_Ricochet( ptr->vecEndPos, RANDOM_FLOAT( 0.5, 1.5 ) );
// EMIT_SOUND_DYN( ENT(pev), CHAN_BODY, pRicSounds[ RANDOM_LONG(0,ARRAYSIZE(pRicSounds)-1) ], 1.0, ATTN_NORM, 0, PITCH_NORM );
}
flDamage *= (1.00f - gSkillData.rgruntArmor); // cut damage
}
// Lower protection against explosions
else if ( bitsDamageType & DMG_BLAST )
flDamage *= (1.00f - (gSkillData.rgruntArmor / 2.00f)); // 50% less protection
// No protection at all against other types of damages
CMBaseMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
}
//=========================================================
// TakeDamage - Robo Grunts should not take cover as soon
// as they take damage.
//=========================================================
int CMRGrunt::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
{
return CMBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
}
//=========================================================
// Spawn
//=========================================================
void CMRGrunt::Spawn()
{
Precache();
SET_MODEL(ENT(pev), (!FStringNull( pev->model ) ? STRING( pev->model ) : "models/rgrunt.mdl"));
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = DONT_BLEED;
pev->effects = 0;
if (!pev->health) { pev->health = gSkillData.rgruntHealth; }
pev->max_health = pev->health; // to determine when sparks should be emitted
m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
m_flNextGrenadeCheck = gpGlobals->time + 1;
m_flNextPainTime = gpGlobals->time;
m_flNextSpark = gpGlobals->time; // when to emit sparks again
m_flNextDischarge = gpGlobals->time; // when electric shell should activate
m_flActiveDischarge = 0; // how long to sustain the electricity
m_iSentence = -1;
//m_afCapability = bits_CAP_SQUAD | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
m_afCapability = bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
//m_fEnemyEluded = FALSE;
m_fFirstEncounter = TRUE;// this is true when the grunt spawns, because he hasn't encountered an enemy yet.
m_HackedGunPos = Vector(0, 0, 55);
if (pev->weapons == 0)
{
// weapons not specified, randomize
switch(RANDOM_LONG(0, 2))
{
case 0:
pev->weapons = RGRUNT_9MMAR | RGRUNT_HANDGRENADE;
break;
case 1:
pev->weapons = RGRUNT_SHOTGUN;
break;
case 2:
pev->weapons = RGRUNT_9MMAR | RGRUNT_GRENADELAUNCHER;
break;
}
}
if (FBitSet(pev->weapons, RGRUNT_SHOTGUN))
{
SetBodygroup(GUN_GROUP, GUN_SHOTGUN);
m_cClipSize = 8;
}
else
{
m_cClipSize = RGRUNT_CLIP_SIZE;
}
m_cAmmoLoaded = m_cClipSize;
CMTalkMonster::g_talkWaitTime = 0;
MonsterInit();
SetTouch( &CMRGrunt::SparkTouch );
pev->classname = MAKE_STRING( "monster_robogrunt" );
if ( strlen( STRING( m_szMonsterName ) ) == 0 )
{
// default name
m_szMonsterName = MAKE_STRING( "Robo Grunt" );
}
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CMRGrunt::Precache()
{
PRECACHE_MODEL("models/rgrunt.mdl");
m_iBodyGibs = PRECACHE_MODELINDEX( "models/metalplategibs_green.mdl" );
PRECACHE_SOUND("hgrunt/gr_mgun1.wav");
PRECACHE_SOUND("hgrunt/gr_mgun2.wav");
PRECACHE_SOUND("turret/tu_die.wav");
PRECACHE_SOUND("turret/tu_die2.wav");
PRECACHE_SOUND("buttons/spark1.wav");
PRECACHE_SOUND("buttons/spark2.wav");
PRECACHE_SOUND("buttons/spark3.wav");
PRECACHE_SOUND("buttons/spark4.wav");
PRECACHE_SOUND("buttons/spark5.wav");
PRECACHE_SOUND("buttons/spark6.wav");
PRECACHE_SOUND("debris/beamstart14.wav");
PRECACHE_SOUND("hgrunt/gr_reload1.wav");
PRECACHE_SOUND("weapons/glauncher.wav");
PRECACHE_SOUND("weapons/sbarrel1.wav");
PRECACHE_SOUND("zombie/claw_miss2.wav");// because we use the basemonster SWIPE animation event
// get voice pitch
m_voicePitch = 115; // always the same
m_iBrassShell = PRECACHE_MODELINDEX("models/shell.mdl");// brass shell
}

456
src/dlls/ripent.cpp Normal file
View File

@@ -0,0 +1,456 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
****/
// this is a stripped down "bspfile.c" file containing only entity data similar
// to using a ripent tool to read ents from a bsp, hence the name.
// -Giegue
#include "extdll.h"
#include "ripent.h"
#include "meta_api.h"
#if defined linux
#include <sys/stat.h>
#endif
//=============================================================================
int entdatasize;
char dentdata[MAX_MAP_ENTSTRING];
int num_entities;
entity_t entities[MAX_MAP_ENTITIES];
//=============================================================================
dheader_t *header;
int CopyLump(int lump, void *dest, int size)
{
int length, ofs;
length = header->lumps[lump].filelen;
ofs = header->lumps[lump].fileofs;
if (length % size)
{
LOG_MESSAGE(PLID, "LoadBSPFile: odd lump size");
return 0;
}
memcpy(dest, (byte *)header + ofs, length);
return length / size;
}
/*
=============
LoadBSPFile
=============
*/
void LoadBSPFile(char *filename)
{
//int i;
// reset these values
entdatasize = 0;
num_entities = 0;
memset(dentdata, 0, sizeof(dentdata));
memset(entities, 0, sizeof(entities));
//
// load the file header
//
if (LoadFile(filename, (void **)&header) == -1)
return;
// UNDONE: there is no need to swap it...? -Giegue
// swap the header
/*for (i = 0; i < sizeof(dheader_t) / 4; i++)
((int *)header)[i] = LittleLong(((int *)header)[i]);*/
// game will not load the BSP if it's invalid.
// so if this is called, it means something went really wrong loading it
if (header->version != BSPVERSION)
{
LOG_MESSAGE(PLID, "%s is version %i, not %i", filename, header->version, BSPVERSION);
return;
}
entdatasize = CopyLump(LUMP_ENTITIES, dentdata, 1);
free(header); // everything has been copied out
}
//============================================================================
/*
=================
ParseEpair
=================
*/
epair_t *ParseEpair(void)
{
epair_t *e;
e = (epair_t*)malloc(sizeof(epair_t));
memset(e, 0, sizeof(epair_t));
if (strlen(token) >= MAX_KEY - 1)
{
LOG_MESSAGE(PLID, "ParseEpar: token key too long");
return NULL;
}
e->key = copystring(token);
GetToken(false);
if (strlen(token) >= MAX_VALUE - 1)
{
LOG_MESSAGE(PLID, "ParseEpar: token value too long");
return NULL;
}
e->value = copystring(token);
return e;
}
/*
================
ParseEntity
================
*/
bool ParseEntity(void)
{
epair_t *e;
entity_t *mapent;
if (!GetToken(true))
return false;
if (strcmp(token, "{"))
{
LOG_MESSAGE(PLID, "ParseEntity: { not found");
return false;
}
if (num_entities == MAX_MAP_ENTITIES)
{
LOG_MESSAGE(PLID, "num_entities == MAX_MAP_ENTITIES");
return false;
}
mapent = &entities[num_entities];
num_entities++;
do
{
if (!GetToken(true))
{
LOG_MESSAGE(PLID, "ParseEntity: EOF without closing brace");
return false;
}
if (!strcmp(token, "}"))
break;
e = ParseEpair();
e->next = mapent->epairs;
mapent->epairs = e;
} while (1);
return true;
}
/*
================
ParseEntities
Parses the dentdata string into entities
================
*/
void ParseEntities(void)
{
num_entities = 0;
ParseFromMemory(dentdata, entdatasize);
while (ParseEntity())
{
}
}
// --
/* MERGE cmdlib.c AND scriplib.c INTO ripent.cpp */
/* Only add needed functions. */
// --
// -- cmdlib.c --
char qdir[1024] = { '\0' };
int LoadFile(char *filename, void **bufferptr)
{
FILE *f;
int length;
void *buffer;
f = SafeOpenRead(filename);
if (f == NULL)
return -1; // error
#if defined (_WIN32)
length = filelength(fileno(f));
#else
struct stat st; stat(filename, &st);
length = st.st_size;
#endif
buffer = malloc(length + 1);
((char *)buffer)[length] = 0;
SafeRead(f, buffer, length);
fclose(f);
*bufferptr = buffer;
return length;
}
int LittleLong(int l)
{
byte b1, b2, b3, b4;
b1 = l & 255;
b2 = (l >> 8) & 255;
b3 = (l >> 16) & 255;
b4 = (l >> 24) & 255;
return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4;
}
char *copystring(char *s)
{
char *b;
b = (char*)malloc(strlen(s) + 1);
strcpy(b, s);
return b;
}
FILE *SafeOpenRead(char *filename)
{
FILE *f;
f = fopen(filename, "rb");
if (!f)
{
LOG_MESSAGE(PLID, "Error opening %s: %s", filename, strerror(errno));
return NULL;
}
return f;
}
void SafeRead(FILE *f, void *buffer, int count)
{
if (fread(buffer, 1, count, f) != (size_t)count)
{
LOG_MESSAGE(PLID, "File read failure");
return;
}
}
char *ExpandPath(char *path)
{
char *psz;
static char full[1024];
if (!qdir)
{
LOG_MESSAGE(PLID, "ExpandPath called without qdir set");
return NULL;
}
if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
return path;
psz = strstr(path, qdir);
if (psz)
strcpy(full, path);
else
sprintf(full, "%s%s", qdir, path);
return full;
}
// -- scriplib.c --
typedef struct
{
char filename[1024];
char *buffer, *script_p, *end_p;
int line;
} script_t;
#define MAX_INCLUDES 8
script_t scriptstack[MAX_INCLUDES];
script_t *script;
int scriptline;
char token[MAXTOKEN];
bool endofscript;
bool tokenready; // only true if UnGetToken was just called
void ParseFromMemory(char *buffer, int size)
{
script = scriptstack;
script++;
if (script == &scriptstack[MAX_INCLUDES])
{
LOG_MESSAGE(PLID, "script file exceeded MAX_INCLUDES");
return;
}
strcpy(script->filename, "memory buffer");
script->buffer = buffer;
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
endofscript = false;
tokenready = false;
}
bool EndOfScript(bool crossline)
{
if (!crossline)
{
LOG_MESSAGE(PLID, "Line %i is incomplete", scriptline);
return false;
}
if (!strcmp(script->filename, "memory buffer"))
{
endofscript = true;
return false;
}
free(script->buffer);
if (script == scriptstack + 1)
{
endofscript = true;
return false;
}
script--;
scriptline = script->line;
//printf("returning to %s\n", script->filename);
return GetToken(crossline);
}
void AddScriptToStack(char *filename)
{
int size;
script++;
if (script == &scriptstack[MAX_INCLUDES])
{
LOG_MESSAGE(PLID, "script file exceeded MAX_INCLUDES");
return;
}
strcpy(script->filename, ExpandPath(filename));
size = LoadFile(script->filename, (void **)&script->buffer);
//printf("entering %s\n", script->filename);
script->line = 1;
script->script_p = script->buffer;
script->end_p = script->buffer + size;
}
bool GetToken(bool crossline)
{
char *token_p;
if (tokenready) // is a token allready waiting?
{
tokenready = false;
return true;
}
if (script->script_p >= script->end_p)
return EndOfScript(crossline);
//
// skip space
//
skipspace:
while (*script->script_p <= 32)
{
if (script->script_p >= script->end_p)
return EndOfScript(crossline);
if (*script->script_p++ == '\n')
{
if (!crossline)
{
LOG_MESSAGE(PLID, "Line %i is incomplete", scriptline);
return false;
}
scriptline = script->line++;
}
}
if (script->script_p >= script->end_p)
return EndOfScript(crossline);
if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field
(*script->script_p == '/' && *((script->script_p) + 1) == '/')) // also make // a comment field
{
if (!crossline)
{
LOG_MESSAGE(PLID, "Line %i is incomplete", scriptline);
return false;
}
while (*script->script_p++ != '\n')
if (script->script_p >= script->end_p)
return EndOfScript(crossline);
goto skipspace;
}
//
// copy token
//
token_p = token;
if (*script->script_p == '"')
{
// quoted token
script->script_p++;
while (*script->script_p != '"')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &token[MAXTOKEN])
{
// if the server does not crash before this happens, then monstermod will.
// simulate a fatal error and be verbose on why it happens.
ALERT(at_logged, "FATAL ERROR (shutting down): ReadEntsFromBSP: Line %i is too long (length > %i).", scriptline, MAXTOKEN);
}
}
script->script_p++;
}
else // regular token
while (*script->script_p > 32 && *script->script_p != ';')
{
*token_p++ = *script->script_p++;
if (script->script_p == script->end_p)
break;
if (token_p == &token[MAXTOKEN])
{
// ditto
ALERT(at_logged, "FATAL ERROR (shutting down): ReadEntsFromBSP: Line %i is too long (length > %i).", scriptline, MAXTOKEN);
}
}
*token_p = 0;
if (!strcmp(token, "$include"))
{
GetToken(false);
AddScriptToStack(token);
return GetToken(crossline);
}
return true;
}

Some files were not shown because too many files have changed in this diff Show More