diff --git a/config/menus.cfg b/config/menus.cfg index 7b320cae..b40ceb9d 100755 --- a/config/menus.cfg +++ b/config/menus.cfg @@ -1,512 +1,512 @@ -// standard menu definitions - -bind ESCAPE "showmenu main" // it all starts here - -newmenu main - -menuitem "Multiplayer" "showmenu multiplayer" -menuitem "Singleplayer" "showmenu singleplayer" -menuitem "Team/Player Setup" "showmenu setup" -menuitem "Load Map" "showmenu maps" -menuitem "Options" "showmenu options" -menuitem "Editing" "showmenu editing" -menuitem "About/Credits/Help" "showmenu about" -menuitem "Quit" "quit" - - -// menumdl path frame range rotation-speed{0..100} scale{0..100} -// chmenumdl menuname newpath - -alias genmapitems [ - alias n (listlen $arg1) - loop $n [ - at $arg1 $i - alias mapname $s - concat map $s - menuitem $s - alias next (+ $i 1) - if (= $next $n) [ alias next 0 ] [] - at $arg1 $next - alias nextmap $s - concatword nextmap_ $mapname - alias $s $nextmap - ] -] - -newmenu maps - -genmapitems "ac_complex ac_mines ac_depot ac_desert" - -newmenu maps_ctf - -genmapitems "ac_mines ac_depot" - -newmenu setup - -menuitem "Select Team" "showmenu team" -menuitem "Select Skins" "showmenu skins" -menuitem "Select Weapon" "showmenu weapons" -menuitem "Select Crosshair" "showmenu crosshairs" -menuitem "Set Name" "saycommand /name" - -newmenu skins - -menuitem "CLA Skins" "showmenu cla" -menuitem "RVSF Skins" "showmenu rvsf" - -newmenu "cla" - -menumdl playermodels/terrorist/01/menu 0 197 50 5 -menuitem "Comandante" "skin 0" "chmenumdl cla playermodels/terrorist/01/menu 0 197 50 5" -menuitem "Psycho" "skin 1" "chmenumdl cla playermodels/terrorist/02/menu 0 197 50 5" -menuitem "Bomber" "skin 2" "chmenumdl cla playermodels/terrorist/03/menu 0 197 50 5" -menuitem "Ripper" "skin 3" "chmenumdl cla playermodels/terrorist/04/menu 0 197 50 5" - - -newmenu "rvsf" - -menumdl playermodels/counterterrorist/01/menu 0 197 50 5 -menuitem "Alpha" "skin 0" "chmenumdl rvsf playermodels/counterterrorist/01/menu 0 197 50 5" -menuitem "Tango" "skin 1" "chmenumdl rvsf playermodels/counterterrorist/02/menu 0 197 50 5" -menuitem "Cobra" "skin 2" "chmenumdl rvsf playermodels/counterterrorist/03/menu 0 197 50 5" -menuitem "Viper" "skin 3" "chmenumdl rvsf playermodels/counterterrorist/04/menu 0 197 50 5" -menuitem "Swat" "skin 4" "chmenumdl rvsf playermodels/counterterrorist/05/menu 0 197 50 5" -menuitem "Police" "skin 5" "chmenumdl rvsf playermodels/counterterrorist/06/menu 0 197 50 5" - - -newmenu team - -menumdl playermodels/terrorist/01/menu 0 197 50 5 -menuitem "Cuban Liberations Army" "team CLA" "chmenumdl team playermodels/terrorist/01/menu 0 197 50 5" -menuitem "Rabid Viper Special Forces" "team RVSF" "chmenumdl team playermodels/counterterrorist/03/menu 0 197 50 5" - - - -alias gencrosshairs [ - alias n (listlen $arg1) - loop $n [ - at $arg1 $i - alias label $s - concat loadcrosshair $s - menuitem $label $s - ] -] - -newmenu crosshairs - -gencrosshairs "default.png cube.png dot.png dot_wide.png o.png o_dot.png o_x.png star.png wide.png x-dot.png" - - -newmenu multiplayer - -menuitem "Join Game" "servermenu" -menuitem "Update Servers" "updatefrommaster" -menuitem "Vote" "showmenu gamemode" -menuitem "Disconnect" "disconnect" - - -newmenu gamemode - -menuitem "Team Deathmatch" "mode 0; showmenu maps" -menuitem "Deathmatch" "mode 2; showmenu maps" -menuitem "Team Survivor" "mode 4; showmenu maps" -menuitem "Survivor" "mode 3; showmenu maps" -menuitem "Capture the Flag" "mode 5; showmenu maps_ctf" -menuitem "Pistol Frenzy" "mode 6; showmenu maps" -menuitem "Last Swiss Standing" "mode 9; showmenu maps" - - - -// bot menus and tools - -alias tmp_botskill good -alias tmp_numbots 1 -alias tmp_mode -alias tmp_botmap - -alias startbotmatch [ - kickallbots - addnbot (div $tmp_numbots 2) RVSF $tmp_botskill - if ((> (mod $tmp_numbots 2) 0)) [ alias tmp_numbots (+ $tmp_numbots 1) ] [] - addnbot (div $tmp_numbots 2) CLA $tmp_botskill -] - -alias startbotmap [ - disconnect - echo starting botmatch.. - sleep 5000 startbotmatch - mode $tmp_mode - map $tmp_botmap -] - -newmenu singleplayer - -// teamplay note mature yet -//menuitem "Bot Team Deathmatch" "alias tmp_mode 7; showmenu botskill" -menuitem "Bot Deathmatch" "alias tmp_mode 8; showmenu botskill" - -newmenu botskill - -alias showmenu_enemies [ if (= $tmp_mode 8) [ showmenu enemies ] [ showmenu "team enemies" ] ] -menuitem "best" "alias tmp_botskill best; showmenu_enemies" -menuitem "good (default)" "alias tmp_botskill good; showmenu_enemies" -menuitem "medium" "alias tmp_botskill medium; showmenu_enemies" -menuitem "worse" "alias tmp_botskill worse; showmenu_enemies" -menuitem "bad" "alias tmp_botskill bad; showmenu_enemies" - - -alias genenemyitems [ - alias n (listlen $arg1) - loop $n [ - at $arg1 $i - alias numplayers $s - if (= $arg2 0) [ // DM - alias numplayers (- $numplayers 1) // don't count yourself as enemy - if (= $numplayers 1) [ - concat $numplayers enemy - ] [ - concat $numplayers enemies - ] - ] [ // TDM - alias teamsize (div $numplayers 2) - concatword $teamsize on $teamsize - ] - alias menutext $s - concat "alias tmp_numbots" $numplayers "; showmenu botmaps" - menuitem $menutext $s - ] -] - -newmenu enemies -genenemyitems "2 3 5 9 17 33" 0 - -newmenu "team enemies" -genenemyitems "2 4 6 8 16 32" 1 - - -newmenu botmaps - -alias genbotmaps [ - alias n (listlen $arg1) - loop $n [ - at $arg1 $i - alias mapname $s - concat map $mapname - alias menutext $s - concat "alias tmp_botmap" $mapname "; startbotmap" - menuitem $menutext $s - ] -] - -genbotmaps "ac_complex ac_mines ac_depot ac_desert" - -newmenu master - -menuitem "Master Login" "saycommand /masterlogin " -menuitem "Change Mode/Map" "showmenu gamemode" -menuitem "Kick Player" "showmastermenu 0" -menuitem "Ban Player" "showmastermenu 1" -menuitem "Remove Bans" "mastercommand 2" - - -newmenu editing - -menuitem "Mapmodels..." "showmenu mapmodels" -menuitem "Entities" "showmenu entities" -menuitem "Pickups" "showmenu pickups" -menuitem "Arches and slopes.." "showmenu arches" -menuitem "Map operations.." "showmenu mapop" -menuitem "help..." "showmenu editkeys" - - -newmenu editkeys - -menuitem "toggle edit mode (key E)" "edittoggle" -menuitem "undo last edit action (key U)" "undo" -menuitem "copy selection (key C)" "copy" -menuitem "paste selection (red vertex = upper left, key V)" "paste" -menuitem "repeat last texture replace" "replace" -menuitem "delete closest entity (key X)" "delent" -menuitem "fullbright view (key f7)" "fullbright 1" -menuitem "recalc light (key f8)" "recalc" -menuitem "toggle show geometric mipmaps (key f5)" "showmip" -menuitem "toggle occlusion culling (key f6) "toggleocull" -menuitem "more..." "showmenu more" - - -newmenu more - -menuitem "insert/home/pgup/keyp7 browse through floor/wall/ceiling/" "" -menuitem " upper textures on your current selection," "" -menuitem " delete/end/pgup/keyp4 browse backwards" "" -menuitem "[ and ] move the currently selected floor up and down" "" -menuitem " O and P do the same for the ceiling" "" -menuitem "F makes the current selection SOLID, G makes it SPACE" "" -menuitem "K makes something a corner (slant)" "" -menuitem ", and . equalize the floor/ceiling ceiling level" "" -menuitem "H makes the floor a heightfield, I the ceiling" "" -menuitem "8/9 change the offset of a vertex in a heightfield" "" - - -newmenu mapmodels - -menuitem "misc" "showmenu misc" -menuitem "ladders" "showmenu ladders" -menuitem "street" "showmenu street" -menuitem "plants" "showmenu plants" -menuitem "interior" "showmenu interior" -menuitem "lights" "showmenu lights" -menuitem "industrial" "showmenu industrial" -menuitem "signs" "showmenu signs" -menuitem "other" "showmenu other" - - -newmenu misc - -menuitem "Nothing (clip)" "newent mapmodel 0" -menuitem "Bridge(8x8)" "newent mapmodel 1" - - -newmenu ladders - -menuitem "Ladder(7)" "newent mapmodel 2" -menuitem "Ladder(8)" "newent mapmodel 3" -menuitem "Ladder(10)" "newent mapmodel 4" -menuitem "Ladder(11)" "newent mapmodel 5" -menuitem "Ladder(15)" "newent mapmodel 6" - - -newmenu street - -menuitem "Streetlight" "newent mapmodel 7" -menuitem "Bench" "newent mapmodel 9" -menuitem "Dumpster" "newent mapmodel 10" -menuitem "Roadblock" "newent mapmodel 11" -menuitem "Roadblock2" "newent mapmodel 12" -menuitem "Fence" "newent mapmodel 13" -menuitem "Fencepost" "newent mapmodel 14" -menuitem "Fencegate" "newent mapmodel 15" -menuitem "Fencedoor" "newent mapmodel 16" - -newmenu plants - -menuitem "Grass1" "newent mapmodel 17" -menuitem "Grass1_dry" "newent mapmodel 18" -menuitem "Grass1_snow" "newent mapmodel 19" -menuitem "Grass2" "newent mapmodel 20" -menuitem "Grass2_dry" "newent mapmodel 21" -menuitem "Grass2_snow" "newent mapmodel 22" -menuitem "Plant1" "newent mapmodel 23" -menuitem "Plant1_dry" "newent mapmodel 24" -menuitem "Plant1_snow" "newent mapmodel 25" -menuitem "Tree" "newent mapmodel 26" - -newmenu interior - -menuitem "Chair" "newent mapmodel 27" -menuitem "Laptop" "newent mapmodel 28" -menuitem "Picture1" "newent mapmodel 29" -menuitem "Locker" "newent mapmodel 30" - - -newmenu lights - -menuitem "Strahler" "newent mapmodel 31" -menuitem "Light1" "newent mapmodel 32" -menuitem "Bulb" "newent mapmodel 33" - -newmenu industrial - -menuitem "Barrel" "newent mapmodel 34" -menuitem "Knocked Over Barrel" "newent mapmodel 35" -menuitem "Electric meter" "newent mapmodel 36" -menuitem "Pallette" "newent mapmodel 37" -menuitem "Gastank" "newent mapmodel 38" -menuitem "Grate (horizontal)" "newent mapmodel 39" -menuitem "Grate (vertical)" "newent mapmodel 40" -menuitem "Wrench" "newent mapmodel 41" -menuitem "Screw" "newent mapmodel 42" -menuitem "Hook" "newent mapmodel 52" - -newmenu signs - -menuitem "Flammable Sign" "newent mapmodel 43" -menuitem "Speed Limit Sign" "newent mapmodel 44" -menuitem "Maintenance Sign" "newent mapmodel 45" -menuitem "Caution Sign" "newent mapmodel 46" -menuitem "Biohazard Sign" "newent mapmodel 47" - -newmenu other - -menuitem "Cigarette" "newent mapmodel 48" -menuitem "Can" "newent mapmodel 49" -menuitem "Fallen Can" "newent mapmodel 50" -menuitem "Broken Wood" "newent mapmodel 51" -menuitem "Coffee" "newent mapmodel 53" -menuitem "Flyer" "newent mapmodel 54" -menuitem "Poster" "newent mapmodel 55" - -newmenu entities - -menuitem spawn_RVSF "newent playerstart 1" -menuitem spawn_CLA "newent playerstart 0" -menuitem spawn_ffa "newent playerstart 100" -menuitem flag_RVSF "newent ctf-flag 1" -menuitem flag_CLA "newent ctf-flag 0" -menuitem ladder "newent ladder" - -newmenu pickups - -menuitem "Health" "newent health" -menuitem "Pistol Ammo" "newent clips" -menuitem "Box of Ammo" "newent ammobox" -menuitem "Kevlar Vest" "newent armour" -menuitem "Akimbo" "newent akimbo" - -newmenu arches - -menuitem "normal arch" "heightfield 2; arch 0" -menuitem "arch with sideways curve (delta 1)" "heightfield 2; arch 1" -menuitem "arch with sideways curve (delta 2)" "heightfield 2; arch 2" -menuitem "arch with sideways curve (delta 3)" "heightfield 2; arch 3" -menuitem "arch with sideways curve (delta 4)" "heightfield 2; arch 4" -menuitem "slope increase 2 left-right" "heightfield 0; slope 2 0" -menuitem "slope decrease 2 left-right" "heightfield 0; slope -2 0" -menuitem "slope increase 2 top-bottom" "heightfield 0; slope 0 2" -menuitem "slope decrease 2 top-bottom" "heightfield 0; slope 0 -2" -menuitem "slope increase 1 left-right" "heightfield 0; slope 1 0" -menuitem "slope decrease 1 left-right" "heightfield 0; slope -1 0" -menuitem "slope increase 1 top-bottom" "heightfield 0; slope 0 1" -menuitem "slope decrease 1 top-bottom" "heightfield 0; slope 0 -1" -menuitem "fix heightfield" "slope 0 0" -menuitem "[ arches make ceiling heighfield, slopes floor ]" - - -newmenu mapop - -menuitem "Newmap 128x128 cubes (recommended)" "newmap 7" -menuitem "Newmap 256x256 cubes" "newmap 8" -menuitem "Increase mapsize (2x)" "mapenlarge" -menuitem "Set map title/author" "saycommand /mapmsg" - -bind B "showmenu weapons" - -//newmenu items -//menubg "textures/makke/menu.jpg" - -//menuitem "Primary Weapon" "showmenu primary" -//menuitem "Secondary Weapon" "showmenu secondary" -//menuitem "Equipment" "showmenu equipment" - -newmenu "weapons" - -menumdl weapons/assault/menu 0 1 75 12 -menuitem "Mtp 57 Assault Rifle" "item 5;echo MK-77 Assault Rifle chosen" "chmenumdl weapons weapons/assault/menu 0 1 75 12" -menuitem "A-ARD/10 Submachine Gun" "item 3;echo A-ARD/10 Submachine Gun chosen" "chmenumdl weapons weapons/subgun/menu 0 1 75 12" -menuitem "Precision Tech AD-81 Sniper Rifle" "item 4,echo Precision Tech AD-81 Sniper Rifle chosen" "chmenumdl weapons weapons/sniper/menu 0 1 75 12" -menuitem "V-19 Combat Shotgun" "item 2;echo V-19 Combat Shotgun chosen" "chmenumdl weapons weapons/shotgun/menu 0 1 75 12" - - -//newmenu "secondary" -//menumdl vwep/semipistol 0 1 40 60 -//menuitem "Mk-77 Semi-Automatic Pistol" "item 1;echo MTP 57 Semi-Automatic Pistol Chosen" - -//newmenu "equipment" -//menumdl vwep/grenade_static 0 1 40 80 -//menuitem "DR-17 HE-Grenade" "echo DR-17 HE-Grenade chosen" "chmenumdl equipment vwep/grenade_static 0 1 40 80" -//menuitem "SN-Tech Kelvar Vest" "echo SN-Tech Kelvar Vest chosen" "chmenumdl equipment pickups/kevlar 0 1 40 20" - -newmenu options - -menuitem "tweak minlod.. (higher = less popup, possibly lower fps)" "showmenu minlod" -menuitem "tweak fpsrange.. (higher = possibly more popup)" "showmenu fpsrange" -menuitem "tweak water subdivision.." "showmenu watersubdiv" -menuitem "turn dynamic light/shadows off" "dynlight 0" -menuitem "tweak gamma.." "showmenu gamma" - -newmenu gamma - -menuitem "gamma 50" -menuitem "gamma 60" -menuitem "gamma 70" -menuitem "gamma 80" -menuitem "gamma 90" -menuitem "gamma 100" -menuitem "gamma 110" -menuitem "gamma 120" -menuitem "gamma 130" -menuitem "gamma 140" -menuitem "gamma 150" - -newmenu minlod - -menuitem "minimum (25)" "minlod 25" -menuitem "decent (60)" "minlod 60" -menuitem "good (100)" "minlod 100" -menuitem "fps be damned (250)" "minlod 250" - -newmenu fpsrange - -menuitem "my 486 0wnz y00 (8-10)" "fpsrange 8 10" -menuitem "slow machine (20-25)" "fpsrange 20 25" -menuitem "sensible default (30-40)" "fpsrange 30 40" -menuitem "fps whore (60-60)" "fpsrange 60 60" -menuitem "I don't understand LOD (100+)" "fpsrange 100 1000" - -newmenu watersubdiv - -menuitem "subdivision 1 (insane polygon wastage)" "watersubdiv 1" -menuitem "subdivision 2 (high quality)" "watersubdiv 2" -menuitem "subdivision 4 (medium quality)" "watersubdiv 4" -menuitem "subdivision 8 (low quality)" "watersubdiv 8" -menuitem "subdivision 16 (my 486 can do water too)" "watersubdiv 16" - - -newmenu about - -menuitem "ActionCube v.0.9" "" -menuitem "" -menuitem " ...help" "showmenu help" -menuitem " ...credits" "showmenu credits" -menuitem "" -menuitem "by 'Rabid Viper Productions'" "showmenu credits" -menuitem "http://action.cubers.net" "echo sorry no built-in web browser yet :)" -menuitem "a cube mod/tc based on the" "" -menuitem "" -menuitem "Cube game/engine" " " -menuitem "by Wouter 'Aardappel' van Oortmerssen" "echo ..yes, the uber-coder" -menuitem "http://www.cubeengine.com/" "echo sorry no built-in web browser yet :)" - - - -newmenu help - -menuitem "r - reload Gun" "" -menuitem "right mouse button - use scope" "" -menuitem "Mousewheel Up/Down - cycle weapons" "" -menuitem "" -menuitem "b - Outfit Menu" "" -menuitem "" "" -menuitem "-for further information read readme.html-" - -newmenu credits - -menuitem "Arghvark Project Leader" "" -menuitem " Concept, Coding" "" -menuitem "Verbal QA, Advisor, Lead Tester" "" -menuitem "driAn Lead Coder, Webdesign" "" -menuitem "makkE Lead Artist" "" -menuitem " Maps, Models, Skins, Animation" "" -menuitem " Sound, some Textures, 2D-Art" "" -menuitem "Nieb Models, Hosting" "" -menuitem "Mitaman Maps,Ressources" "" -menuitem "Rick Bots, Win32-Compiling" "" -menuitem "" -menuitem "Thanks to:" "" -menuitem "Wouter van Oortmersson (Engine), DCP (Music)," "" -menuitem "JCDPC (Laptop Model, Company), dtd (Hosting), Boeck" "" -menuitem "Ted Southard (DigitalFlux), Noctua Graphics, Arcitool," -menuitem "Craig Fortune, 3dcafe, Rohrschach, lemong.fr," -menuitem "Mayang.com, Chris Zastrow, imageafter.com (textures)" - -alias master [ showmenu master ] +// standard menu definitions + +bind ESCAPE "showmenu main" // it all starts here + +newmenu main + +menuitem "Multiplayer" "showmenu multiplayer" +menuitem "Singleplayer" "showmenu singleplayer" +menuitem "Team/Player Setup" "showmenu setup" +menuitem "Load Map" "showmenu maps" +menuitem "Options" "showmenu options" +menuitem "Editing" "showmenu editing" +menuitem "About/Credits/Help" "showmenu about" +menuitem "Quit" "quit" + + +// menumdl path anim rotation-speed{0..100} scale{0..100} +// chmenumdl menuname newpath + +alias genmapitems [ + alias n (listlen $arg1) + loop $n [ + at $arg1 $i + alias mapname $s + concat map $s + menuitem $s + alias next (+ $i 1) + if (= $next $n) [ alias next 0 ] [] + at $arg1 $next + alias nextmap $s + concatword nextmap_ $mapname + alias $s $nextmap + ] +] + +newmenu maps + +genmapitems "ac_complex ac_mines ac_depot ac_desert" + +newmenu maps_ctf + +genmapitems "ac_mines ac_depot" + +newmenu setup + +menuitem "Select Team" "showmenu team" +menuitem "Select Skins" "showmenu skins" +menuitem "Select Weapon" "showmenu weapons" +menuitem "Select Crosshair" "showmenu crosshairs" +menuitem "Set Name" "saycommand /name" + +newmenu skins + +menuitem "CLA Skins" "showmenu cla" +menuitem "RVSF Skins" "showmenu rvsf" + +newmenu "cla" + +menumdl playermodels/terrorist/01 all 50 4 +menuitem "Comandante" "skin 0" "chmenumdl cla playermodels/terrorist/01 all 50 4" +menuitem "Psycho" "skin 1" "chmenumdl cla playermodels/terrorist/02 all 50 4" +menuitem "Bomber" "skin 2" "chmenumdl cla playermodels/terrorist/03 all 50 4" +menuitem "Ripper" "skin 3" "chmenumdl cla playermodels/terrorist/04 all 50 4" + + +newmenu "rvsf" + +menumdl playermodels/counterterrorist/01 all 50 4 +menuitem "Alpha" "skin 0" "chmenumdl rvsf playermodels/counterterrorist/01 all 50 4" +menuitem "Tango" "skin 1" "chmenumdl rvsf playermodels/counterterrorist/02 all 50 4" +menuitem "Cobra" "skin 2" "chmenumdl rvsf playermodels/counterterrorist/03 all 50 4" +menuitem "Viper" "skin 3" "chmenumdl rvsf playermodels/counterterrorist/04 all 50 4" +menuitem "Swat" "skin 4" "chmenumdl rvsf playermodels/counterterrorist/05 all 50 4" +menuitem "Police" "skin 4" "chmenumdl rvsf playermodels/counterterrorist/06 all 50 4" + + +newmenu team + +menumdl playermodels/terrorist/01 all 50 4 +menuitem "Cuban Liberations Army" "team CLA" "chmenumdl team playermodels/terrorist/01 all 50 4" +menuitem "Rabid Viper Special Forces" "team RVSF" "chmenumdl team playermodels/counterterrorist/03 all 50 4" + + + +alias gencrosshairs [ + alias n (listlen $arg1) + loop $n [ + at $arg1 $i + alias label $s + concat loadcrosshair $s + menuitem $label $s + ] +] + +newmenu crosshairs + +gencrosshairs "default.png cube.png dot.png dot_wide.png o.png o_dot.png o_x.png star.png wide.png x-dot.png" + + +newmenu multiplayer + +menuitem "Join Game" "servermenu" +menuitem "Update Servers" "updatefrommaster" +menuitem "Vote" "showmenu gamemode" +menuitem "Disconnect" "disconnect" + + +newmenu gamemode + +menuitem "Team Deathmatch" "mode 0; showmenu maps" +menuitem "Deathmatch" "mode 2; showmenu maps" +menuitem "Team Survivor" "mode 4; showmenu maps" +menuitem "Survivor" "mode 3; showmenu maps" +menuitem "Capture the Flag" "mode 5; showmenu maps_ctf" +menuitem "Pistol Frenzy" "mode 6; showmenu maps" +menuitem "Last Swiss Standing" "mode 9; showmenu maps" + + + +// bot menus and tools + +alias tmp_botskill good +alias tmp_numbots 1 +alias tmp_mode +alias tmp_botmap + +alias startbotmatch [ + kickallbots + addnbot (div $tmp_numbots 2) RVSF $tmp_botskill + if ((> (mod $tmp_numbots 2) 0)) [ alias tmp_numbots (+ $tmp_numbots 1) ] [] + addnbot (div $tmp_numbots 2) CLA $tmp_botskill +] + +alias startbotmap [ + disconnect + echo starting botmatch.. + sleep 5000 startbotmatch + mode $tmp_mode + map $tmp_botmap +] + +newmenu singleplayer + +// teamplay note mature yet +//menuitem "Bot Team Deathmatch" "alias tmp_mode 7; showmenu botskill" +menuitem "Bot Deathmatch" "alias tmp_mode 8; showmenu botskill" + +newmenu botskill + +alias showmenu_enemies [ if (= $tmp_mode 8) [ showmenu enemies ] [ showmenu "team enemies" ] ] +menuitem "best" "alias tmp_botskill best; showmenu_enemies" +menuitem "good (default)" "alias tmp_botskill good; showmenu_enemies" +menuitem "medium" "alias tmp_botskill medium; showmenu_enemies" +menuitem "worse" "alias tmp_botskill worse; showmenu_enemies" +menuitem "bad" "alias tmp_botskill bad; showmenu_enemies" + + +alias genenemyitems [ + alias n (listlen $arg1) + loop $n [ + at $arg1 $i + alias numplayers $s + if (= $arg2 0) [ // DM + alias numplayers (- $numplayers 1) // don't count yourself as enemy + if (= $numplayers 1) [ + concat $numplayers enemy + ] [ + concat $numplayers enemies + ] + ] [ // TDM + alias teamsize (div $numplayers 2) + concatword $teamsize on $teamsize + ] + alias menutext $s + concat "alias tmp_numbots" $numplayers "; showmenu botmaps" + menuitem $menutext $s + ] +] + +newmenu enemies +genenemyitems "2 3 5 9 17 33" 0 + +newmenu "team enemies" +genenemyitems "2 4 6 8 16 32" 1 + + +newmenu botmaps + +alias genbotmaps [ + alias n (listlen $arg1) + loop $n [ + at $arg1 $i + alias mapname $s + concat map $mapname + alias menutext $s + concat "alias tmp_botmap" $mapname "; startbotmap" + menuitem $menutext $s + ] +] + +genbotmaps "ac_complex ac_mines ac_depot ac_desert" + +newmenu master + +menuitem "Master Login" "saycommand /masterlogin " +menuitem "Change Mode/Map" "showmenu gamemode" +menuitem "Kick Player" "showmastermenu 0" +menuitem "Ban Player" "showmastermenu 1" +menuitem "Remove Bans" "mastercommand 2" + + +newmenu editing + +menuitem "Mapmodels..." "showmenu mapmodels" +menuitem "Entities" "showmenu entities" +menuitem "Pickups" "showmenu pickups" +menuitem "Arches and slopes.." "showmenu arches" +menuitem "Map operations.." "showmenu mapop" +menuitem "help..." "showmenu editkeys" + + +newmenu editkeys + +menuitem "toggle edit mode (key E)" "edittoggle" +menuitem "undo last edit action (key U)" "undo" +menuitem "copy selection (key C)" "copy" +menuitem "paste selection (red vertex = upper left, key V)" "paste" +menuitem "repeat last texture replace" "replace" +menuitem "delete closest entity (key X)" "delent" +menuitem "fullbright view (key f7)" "fullbright 1" +menuitem "recalc light (key f8)" "recalc" +menuitem "toggle show geometric mipmaps (key f5)" "showmip" +menuitem "toggle occlusion culling (key f6) "toggleocull" +menuitem "more..." "showmenu more" + + +newmenu more + +menuitem "insert/home/pgup/keyp7 browse through floor/wall/ceiling/" "" +menuitem " upper textures on your current selection," "" +menuitem " delete/end/pgup/keyp4 browse backwards" "" +menuitem "[ and ] move the currently selected floor up and down" "" +menuitem " O and P do the same for the ceiling" "" +menuitem "F makes the current selection SOLID, G makes it SPACE" "" +menuitem "K makes something a corner (slant)" "" +menuitem ", and . equalize the floor/ceiling ceiling level" "" +menuitem "H makes the floor a heightfield, I the ceiling" "" +menuitem "8/9 change the offset of a vertex in a heightfield" "" + + +newmenu mapmodels + +menuitem "misc" "showmenu misc" +menuitem "ladders" "showmenu ladders" +menuitem "street" "showmenu street" +menuitem "plants" "showmenu plants" +menuitem "interior" "showmenu interior" +menuitem "lights" "showmenu lights" +menuitem "industrial" "showmenu industrial" +menuitem "signs" "showmenu signs" +menuitem "other" "showmenu other" + + +newmenu misc + +menuitem "Nothing (clip)" "newent mapmodel 0" +menuitem "Bridge(8x8)" "newent mapmodel 1" + + +newmenu ladders + +menuitem "Ladder(7)" "newent mapmodel 2" +menuitem "Ladder(8)" "newent mapmodel 3" +menuitem "Ladder(10)" "newent mapmodel 4" +menuitem "Ladder(11)" "newent mapmodel 5" +menuitem "Ladder(15)" "newent mapmodel 6" + + +newmenu street + +menuitem "Streetlight" "newent mapmodel 7" +menuitem "Bench" "newent mapmodel 9" +menuitem "Dumpster" "newent mapmodel 10" +menuitem "Roadblock" "newent mapmodel 11" +menuitem "Roadblock2" "newent mapmodel 12" +menuitem "Fence" "newent mapmodel 13" +menuitem "Fencepost" "newent mapmodel 14" +menuitem "Fencegate" "newent mapmodel 15" +menuitem "Fencedoor" "newent mapmodel 16" + +newmenu plants + +menuitem "Grass1" "newent mapmodel 17" +menuitem "Grass1_dry" "newent mapmodel 18" +menuitem "Grass1_snow" "newent mapmodel 19" +menuitem "Grass2" "newent mapmodel 20" +menuitem "Grass2_dry" "newent mapmodel 21" +menuitem "Grass2_snow" "newent mapmodel 22" +menuitem "Plant1" "newent mapmodel 23" +menuitem "Plant1_dry" "newent mapmodel 24" +menuitem "Plant1_snow" "newent mapmodel 25" +menuitem "Tree" "newent mapmodel 26" + +newmenu interior + +menuitem "Chair" "newent mapmodel 27" +menuitem "Laptop" "newent mapmodel 28" +menuitem "Picture1" "newent mapmodel 29" +menuitem "Locker" "newent mapmodel 30" + + +newmenu lights + +menuitem "Strahler" "newent mapmodel 31" +menuitem "Light1" "newent mapmodel 32" +menuitem "Bulb" "newent mapmodel 33" + +newmenu industrial + +menuitem "Barrel" "newent mapmodel 34" +menuitem "Knocked Over Barrel" "newent mapmodel 35" +menuitem "Electric meter" "newent mapmodel 36" +menuitem "Pallette" "newent mapmodel 37" +menuitem "Gastank" "newent mapmodel 38" +menuitem "Grate (horizontal)" "newent mapmodel 39" +menuitem "Grate (vertical)" "newent mapmodel 40" +menuitem "Wrench" "newent mapmodel 41" +menuitem "Screw" "newent mapmodel 42" +menuitem "Hook" "newent mapmodel 52" + +newmenu signs + +menuitem "Flammable Sign" "newent mapmodel 43" +menuitem "Speed Limit Sign" "newent mapmodel 44" +menuitem "Maintenance Sign" "newent mapmodel 45" +menuitem "Caution Sign" "newent mapmodel 46" +menuitem "Biohazard Sign" "newent mapmodel 47" + +newmenu other + +menuitem "Cigarette" "newent mapmodel 48" +menuitem "Can" "newent mapmodel 49" +menuitem "Fallen Can" "newent mapmodel 50" +menuitem "Broken Wood" "newent mapmodel 51" +menuitem "Coffee" "newent mapmodel 53" +menuitem "Flyer" "newent mapmodel 54" +menuitem "Poster" "newent mapmodel 55" + +newmenu entities + +menuitem spawn_RVSF "newent playerstart 1" +menuitem spawn_CLA "newent playerstart 0" +menuitem spawn_ffa "newent playerstart 100" +menuitem flag_RVSF "newent ctf-flag 1" +menuitem flag_CLA "newent ctf-flag 0" +menuitem ladder "newent ladder" + +newmenu pickups + +menuitem "Health" "newent health" +menuitem "Pistol Ammo" "newent clips" +menuitem "Box of Ammo" "newent ammobox" +menuitem "Kevlar Vest" "newent armour" +menuitem "Akimbo" "newent akimbo" + +newmenu arches + +menuitem "normal arch" "heightfield 2; arch 0" +menuitem "arch with sideways curve (delta 1)" "heightfield 2; arch 1" +menuitem "arch with sideways curve (delta 2)" "heightfield 2; arch 2" +menuitem "arch with sideways curve (delta 3)" "heightfield 2; arch 3" +menuitem "arch with sideways curve (delta 4)" "heightfield 2; arch 4" +menuitem "slope increase 2 left-right" "heightfield 0; slope 2 0" +menuitem "slope decrease 2 left-right" "heightfield 0; slope -2 0" +menuitem "slope increase 2 top-bottom" "heightfield 0; slope 0 2" +menuitem "slope decrease 2 top-bottom" "heightfield 0; slope 0 -2" +menuitem "slope increase 1 left-right" "heightfield 0; slope 1 0" +menuitem "slope decrease 1 left-right" "heightfield 0; slope -1 0" +menuitem "slope increase 1 top-bottom" "heightfield 0; slope 0 1" +menuitem "slope decrease 1 top-bottom" "heightfield 0; slope 0 -1" +menuitem "fix heightfield" "slope 0 0" +menuitem "[ arches make ceiling heighfield, slopes floor ]" + + +newmenu mapop + +menuitem "Newmap 128x128 cubes (recommended)" "newmap 7" +menuitem "Newmap 256x256 cubes" "newmap 8" +menuitem "Increase mapsize (2x)" "mapenlarge" +menuitem "Set map title/author" "saycommand /mapmsg" + +bind B "showmenu weapons" + +//newmenu items +//menubg "textures/makke/menu.jpg" + +//menuitem "Primary Weapon" "showmenu primary" +//menuitem "Secondary Weapon" "showmenu secondary" +//menuitem "Equipment" "showmenu equipment" + +newmenu "weapons" + +menumdl weapons/assault/menu mapmodel 75 12 +menuitem "Mtp 57 Assault Rifle" "item 5;echo MK-77 Assault Rifle chosen" "chmenumdl weapons weapons/assault/menu mapmodel 75 12" +menuitem "A-ARD/10 Submachine Gun" "item 3;echo A-ARD/10 Submachine Gun chosen" "chmenumdl weapons weapons/subgun/menu mapmodel 75 12" +menuitem "Precision Tech AD-81 Sniper Rifle" "item 4,echo Precision Tech AD-81 Sniper Rifle chosen" "chmenumdl weapons weapons/sniper/menu mapmodel 75 12" +menuitem "V-19 Combat Shotgun" "item 2;echo V-19 Combat Shotgun chosen" "chmenumdl weapons weapons/shotgun/menu mapmodel 75 12" + + +//newmenu "secondary" +//menumdl vwep/semipistol mapmodel 40 60 +//menuitem "Mk-77 Semi-Automatic Pistol" "item 1;echo MTP 57 Semi-Automatic Pistol Chosen" + +//newmenu "equipment" +//menumdl vwep/grenade_static mapmodel 40 80 +//menuitem "DR-17 HE-Grenade" "echo DR-17 HE-Grenade chosen" "chmenumdl equipment vwep/grenade_static mapmodel 40 80" +//menuitem "SN-Tech Kelvar Vest" "echo SN-Tech Kelvar Vest chosen" "chmenumdl equipment pickups/kevlar mapmodel 40 20" + +newmenu options + +menuitem "tweak minlod.. (higher = less popup, possibly lower fps)" "showmenu minlod" +menuitem "tweak fpsrange.. (higher = possibly more popup)" "showmenu fpsrange" +menuitem "tweak water subdivision.." "showmenu watersubdiv" +menuitem "turn dynamic light/shadows off" "dynlight 0" +menuitem "tweak gamma.." "showmenu gamma" + +newmenu gamma + +menuitem "gamma 50" +menuitem "gamma 60" +menuitem "gamma 70" +menuitem "gamma 80" +menuitem "gamma 90" +menuitem "gamma 100" +menuitem "gamma 110" +menuitem "gamma 120" +menuitem "gamma 130" +menuitem "gamma 140" +menuitem "gamma 150" + +newmenu minlod + +menuitem "minimum (25)" "minlod 25" +menuitem "decent (60)" "minlod 60" +menuitem "good (100)" "minlod 100" +menuitem "fps be damned (250)" "minlod 250" + +newmenu fpsrange + +menuitem "my 486 0wnz y00 (8-10)" "fpsrange 8 10" +menuitem "slow machine (20-25)" "fpsrange 20 25" +menuitem "sensible default (30-40)" "fpsrange 30 40" +menuitem "fps whore (60-60)" "fpsrange 60 60" +menuitem "I don't understand LOD (100+)" "fpsrange 100 1000" + +newmenu watersubdiv + +menuitem "subdivision 1 (insane polygon wastage)" "watersubdiv 1" +menuitem "subdivision 2 (high quality)" "watersubdiv 2" +menuitem "subdivision 4 (medium quality)" "watersubdiv 4" +menuitem "subdivision 8 (low quality)" "watersubdiv 8" +menuitem "subdivision 16 (my 486 can do water too)" "watersubdiv 16" + + +newmenu about + +menuitem "ActionCube v.0.9" "" +menuitem "" +menuitem " ...help" "showmenu help" +menuitem " ...credits" "showmenu credits" +menuitem "" +menuitem "by 'Rabid Viper Productions'" "showmenu credits" +menuitem "http://action.cubers.net" "echo sorry no built-in web browser yet :)" +menuitem "a cube mod/tc based on the" "" +menuitem "" +menuitem "Cube game/engine" " " +menuitem "by Wouter 'Aardappel' van Oortmerssen" "echo ..yes, the uber-coder" +menuitem "http://www.cubeengine.com/" "echo sorry no built-in web browser yet :)" + + + +newmenu help + +menuitem "r - reload Gun" "" +menuitem "right mouse button - use scope" "" +menuitem "Mousewheel Up/Down - cycle weapons" "" +menuitem "" +menuitem "b - Outfit Menu" "" +menuitem "" "" +menuitem "-for further information read readme.html-" + +newmenu credits + +menuitem "Arghvark Project Leader" "" +menuitem " Concept, Coding" "" +menuitem "Verbal QA, Advisor, Lead Tester" "" +menuitem "driAn Lead Coder, Webdesign" "" +menuitem "makkE Lead Artist" "" +menuitem " Maps, Models, Skins, Animation" "" +menuitem " Sound, some Textures, 2D-Art" "" +menuitem "Nieb Models, Hosting" "" +menuitem "Mitaman Maps,Ressources" "" +menuitem "Rick Bots, Win32-Compiling" "" +menuitem "" +menuitem "Thanks to:" "" +menuitem "Wouter van Oortmersson (Engine), DCP (Music)," "" +menuitem "JCDPC (Laptop Model, Company), dtd (Hosting), Boeck" "" +menuitem "Ted Southard (DigitalFlux), Noctua Graphics, Arcitool," +menuitem "Craig Fortune, 3dcafe, Rohrschach, lemong.fr," +menuitem "Mayang.com, Chris Zastrow, imageafter.com (textures)" + +alias master [ showmenu master ] diff --git a/packages/models/misc/md2.cfg b/packages/models/misc/md2.cfg new file mode 100644 index 00000000..a1e220bc --- /dev/null +++ b/packages/models/misc/md2.cfg @@ -0,0 +1 @@ +mdlscale 200 diff --git a/packages/models/pickups/flags/small_CLA/md2.cfg b/packages/models/pickups/flags/small_CLA/md2.cfg new file mode 100644 index 00000000..8185e92d --- /dev/null +++ b/packages/models/pickups/flags/small_CLA/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 60 + diff --git a/packages/models/pickups/flags/small_RVSF/md2.cfg b/packages/models/pickups/flags/small_RVSF/md2.cfg new file mode 100644 index 00000000..8d01cf63 --- /dev/null +++ b/packages/models/pickups/flags/small_RVSF/md2.cfg @@ -0,0 +1 @@ +mdlscale 60 diff --git a/packages/models/playermodels/counterterrorist/01/menu/skin.jpg b/packages/models/playermodels/counterterrorist/01/menu/skin.jpg deleted file mode 100644 index 517713b0..00000000 Binary files a/packages/models/playermodels/counterterrorist/01/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/01/menu/tris.md2 b/packages/models/playermodels/counterterrorist/01/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/01/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/01/tris.md2 b/packages/models/playermodels/counterterrorist/01/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/01/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/02/menu/skin.jpg b/packages/models/playermodels/counterterrorist/02/menu/skin.jpg deleted file mode 100644 index c4431f4e..00000000 Binary files a/packages/models/playermodels/counterterrorist/02/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/02/menu/tris.md2 b/packages/models/playermodels/counterterrorist/02/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/02/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/02/tris.md2 b/packages/models/playermodels/counterterrorist/02/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/02/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/03/menu/skin.jpg b/packages/models/playermodels/counterterrorist/03/menu/skin.jpg deleted file mode 100644 index 264ab52b..00000000 Binary files a/packages/models/playermodels/counterterrorist/03/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/03/menu/tris.md2 b/packages/models/playermodels/counterterrorist/03/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/03/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/03/tris.md2 b/packages/models/playermodels/counterterrorist/03/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/03/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/04/menu/skin.jpg b/packages/models/playermodels/counterterrorist/04/menu/skin.jpg deleted file mode 100644 index e0fedfea..00000000 Binary files a/packages/models/playermodels/counterterrorist/04/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/04/menu/tris.md2 b/packages/models/playermodels/counterterrorist/04/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/04/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/04/tris.md2 b/packages/models/playermodels/counterterrorist/04/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/04/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/05/menu/skin.jpg b/packages/models/playermodels/counterterrorist/05/menu/skin.jpg deleted file mode 100644 index ac8f8791..00000000 Binary files a/packages/models/playermodels/counterterrorist/05/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/05/menu/tris.md2 b/packages/models/playermodels/counterterrorist/05/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/05/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/05/tris.md2 b/packages/models/playermodels/counterterrorist/05/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/05/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/06/menu/skin.jpg b/packages/models/playermodels/counterterrorist/06/menu/skin.jpg deleted file mode 100644 index 90044fbe..00000000 Binary files a/packages/models/playermodels/counterterrorist/06/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/06/menu/tris.md2 b/packages/models/playermodels/counterterrorist/06/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/06/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/06/tris.md2 b/packages/models/playermodels/counterterrorist/06/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/counterterrorist/06/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/counterterrorist/md2.cfg b/packages/models/playermodels/counterterrorist/md2.cfg new file mode 100644 index 00000000..f2d16e2d --- /dev/null +++ b/packages/models/playermodels/counterterrorist/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 155 +mdltrans 0 0 24 diff --git a/packages/models/playermodels/terrorist/01/menu/skin.jpg b/packages/models/playermodels/terrorist/01/menu/skin.jpg deleted file mode 100644 index 1ac879c7..00000000 Binary files a/packages/models/playermodels/terrorist/01/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/terrorist/01/menu/tris.md2 b/packages/models/playermodels/terrorist/01/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/terrorist/01/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/terrorist/01/tris.md2 b/packages/models/playermodels/terrorist/01/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/terrorist/01/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/terrorist/02/menu/skin.jpg b/packages/models/playermodels/terrorist/02/menu/skin.jpg deleted file mode 100644 index df8b9d20..00000000 Binary files a/packages/models/playermodels/terrorist/02/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/terrorist/02/menu/tris.md2 b/packages/models/playermodels/terrorist/02/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/terrorist/02/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/terrorist/02/tris.md2 b/packages/models/playermodels/terrorist/02/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/terrorist/02/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/terrorist/03/menu/skin.jpg b/packages/models/playermodels/terrorist/03/menu/skin.jpg deleted file mode 100644 index 794a8cf3..00000000 Binary files a/packages/models/playermodels/terrorist/03/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/terrorist/03/menu/tris.md2 b/packages/models/playermodels/terrorist/03/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/terrorist/03/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/terrorist/03/tris.md2 b/packages/models/playermodels/terrorist/03/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/terrorist/03/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/terrorist/04/menu/skin.jpg b/packages/models/playermodels/terrorist/04/menu/skin.jpg deleted file mode 100644 index 34629363..00000000 Binary files a/packages/models/playermodels/terrorist/04/menu/skin.jpg and /dev/null differ diff --git a/packages/models/playermodels/terrorist/04/menu/tris.md2 b/packages/models/playermodels/terrorist/04/menu/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/terrorist/04/menu/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/terrorist/04/tris.md2 b/packages/models/playermodels/terrorist/04/tris.md2 deleted file mode 100644 index e961a296..00000000 Binary files a/packages/models/playermodels/terrorist/04/tris.md2 and /dev/null differ diff --git a/packages/models/playermodels/terrorist/md2.cfg b/packages/models/playermodels/terrorist/md2.cfg new file mode 100644 index 00000000..f2d16e2d --- /dev/null +++ b/packages/models/playermodels/terrorist/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 155 +mdltrans 0 0 24 diff --git a/packages/models/weapons/assault/md3.cfg b/packages/models/weapons/assault/md3.cfg new file mode 100644 index 00000000..fd64e1c3 --- /dev/null +++ b/packages/models/weapons/assault/md3.cfg @@ -0,0 +1,6 @@ +md3load tris_high.md3 +md3skin weapon skin_weapon.jpg +md3skin hands skin_hands.jpg +md3anim "gun idle" 0 1 +md3anim "gun shoot" 8 8 +md3anim "gun reload" 0 1 diff --git a/packages/models/weapons/assault/world/md2.cfg b/packages/models/weapons/assault/world/md2.cfg new file mode 100644 index 00000000..f2d16e2d --- /dev/null +++ b/packages/models/weapons/assault/world/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 155 +mdltrans 0 0 24 diff --git a/packages/models/weapons/grenade/md3.cfg b/packages/models/weapons/grenade/md3.cfg new file mode 100644 index 00000000..f41d5a67 --- /dev/null +++ b/packages/models/weapons/grenade/md3.cfg @@ -0,0 +1,7 @@ +md3load tris_high.md3 +md3skin weapon skin_weapon.jpg +md3skin hands skin_hands.jpg +md3anim "gun idle" 0 1 +md3anim "gun shoot" 8 13 +md3anim "gun reload" 0 1 +md3anim "gun throw" 21 13 diff --git a/packages/models/weapons/grenade/static/md2.cfg b/packages/models/weapons/grenade/static/md2.cfg new file mode 100644 index 00000000..a1e220bc --- /dev/null +++ b/packages/models/weapons/grenade/static/md2.cfg @@ -0,0 +1 @@ +mdlscale 200 diff --git a/packages/models/weapons/grenade/world/md2.cfg b/packages/models/weapons/grenade/world/md2.cfg new file mode 100644 index 00000000..f2d16e2d --- /dev/null +++ b/packages/models/weapons/grenade/world/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 155 +mdltrans 0 0 24 diff --git a/packages/models/weapons/knife/md3.cfg b/packages/models/weapons/knife/md3.cfg new file mode 100644 index 00000000..d5605bae --- /dev/null +++ b/packages/models/weapons/knife/md3.cfg @@ -0,0 +1,6 @@ +md3load tris_high.md3 +md3skin weapon skin_weapon.jpg +md3skin hands skin_hands.jpg +md3anim "gun idle" 0 1 +md3anim "gun shoot" 8 12 +md3anim "gun reload" 0 1 diff --git a/packages/models/weapons/knife/world/md2.cfg b/packages/models/weapons/knife/world/md2.cfg new file mode 100644 index 00000000..f2d16e2d --- /dev/null +++ b/packages/models/weapons/knife/world/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 155 +mdltrans 0 0 24 diff --git a/packages/models/weapons/pistol/md3.cfg b/packages/models/weapons/pistol/md3.cfg new file mode 100644 index 00000000..fd64e1c3 --- /dev/null +++ b/packages/models/weapons/pistol/md3.cfg @@ -0,0 +1,6 @@ +md3load tris_high.md3 +md3skin weapon skin_weapon.jpg +md3skin hands skin_hands.jpg +md3anim "gun idle" 0 1 +md3anim "gun shoot" 8 8 +md3anim "gun reload" 0 1 diff --git a/packages/models/weapons/pistol/world/md2.cfg b/packages/models/weapons/pistol/world/md2.cfg new file mode 100644 index 00000000..f2d16e2d --- /dev/null +++ b/packages/models/weapons/pistol/world/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 155 +mdltrans 0 0 24 diff --git a/packages/models/weapons/shotgun/md3.cfg b/packages/models/weapons/shotgun/md3.cfg new file mode 100644 index 00000000..50e855d9 --- /dev/null +++ b/packages/models/weapons/shotgun/md3.cfg @@ -0,0 +1,6 @@ +md3load tris_high.md3 +md3skin weapon skin_weapon.jpg +md3skin hands skin_hands.jpg +md3anim "gun idle" 0 1 +md3anim "gun shoot" 8 25 +md3anim "gun reload" 0 1 diff --git a/packages/models/weapons/shotgun/world/md2.cfg b/packages/models/weapons/shotgun/world/md2.cfg new file mode 100644 index 00000000..f2d16e2d --- /dev/null +++ b/packages/models/weapons/shotgun/world/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 155 +mdltrans 0 0 24 diff --git a/packages/models/weapons/sniper/md3.cfg b/packages/models/weapons/sniper/md3.cfg new file mode 100644 index 00000000..0cd5a070 --- /dev/null +++ b/packages/models/weapons/sniper/md3.cfg @@ -0,0 +1,6 @@ +md3load tris_high.md3 +md3skin weapon skin_weapon.jpg +md3skin hands skin_hands.jpg +md3anim "gun idle" 0 1 +md3anim "gun shoot" 8 50 +md3anim "gun reload" 0 1 diff --git a/packages/models/weapons/sniper/world/md2.cfg b/packages/models/weapons/sniper/world/md2.cfg new file mode 100644 index 00000000..f2d16e2d --- /dev/null +++ b/packages/models/weapons/sniper/world/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 155 +mdltrans 0 0 24 diff --git a/packages/models/weapons/subgun/md3.cfg b/packages/models/weapons/subgun/md3.cfg new file mode 100644 index 00000000..fd64e1c3 --- /dev/null +++ b/packages/models/weapons/subgun/md3.cfg @@ -0,0 +1,6 @@ +md3load tris_high.md3 +md3skin weapon skin_weapon.jpg +md3skin hands skin_hands.jpg +md3anim "gun idle" 0 1 +md3anim "gun shoot" 8 8 +md3anim "gun reload" 0 1 diff --git a/packages/models/weapons/subgun/world/md2.cfg b/packages/models/weapons/subgun/world/md2.cfg new file mode 100644 index 00000000..f2d16e2d --- /dev/null +++ b/packages/models/weapons/subgun/world/md2.cfg @@ -0,0 +1,2 @@ +mdlscale 155 +mdltrans 0 0 24 diff --git a/source/src/Makefile b/source/src/Makefile index 631d8eb0..2e045ca8 100644 --- a/source/src/Makefile +++ b/source/src/Makefile @@ -1,6 +1,6 @@ CXX=g++ -CXXOPTFLAGS=-Wall -O3 -fsigned-char -fomit-frame-pointer -fpermissive -CXXFLAGS=$(CXXOPTFLAGS) -I../enet/include `sdl-config --cflags` -Wno-deprecated +CXXOPTFLAGS=-O3 -fomit-frame-pointer +CXXFLAGS=$(CXXOPTFLAGS) -I../enet/include `sdl-config --cflags` -fsigned-char -Wall -Wno-deprecated CLIENT_LIBS=-L../enet -lenet `sdl-config --libs` -lSDL_image -lSDL_mixer -lz -lGL -lGLU CLIENT_OBJS= \ diff --git a/source/src/bot/ac_bot.cpp b/source/src/bot/ac_bot.cpp index c60c1051..d0768d6c 100644 --- a/source/src/bot/ac_bot.cpp +++ b/source/src/bot/ac_bot.cpp @@ -17,34 +17,22 @@ extern vector sents; extern int triggertime; extern itemstat itemstats[]; -extern void spawnstate(dynent *d); +extern void spawnstate(playerent *d); //AC Bot class begin void CACBot::Spawn() { // Init all bot variabeles - m_pMyEnt->eyeheight = 4.25f; - m_pMyEnt->aboveeye = 0.7f; - m_pMyEnt->radius = 1.1f; m_pMyEnt->primary = m_pMyEnt->nextprimary = 2 + rnd(4); spawnplayer(m_pMyEnt); - - m_pMyEnt->targetyaw = m_pMyEnt->yaw = m_pMyEnt->targetpitch = m_pMyEnt->pitch = 0.0f; + + m_pMyEnt->primary = m_pMyEnt->nextprimary = 2 + rnd(4); + m_pMyEnt->targetyaw = m_pMyEnt->targetpitch = 0.0f; radd(this->m_pMyEnt); - m_pMyEnt->move = 0; - m_pMyEnt->enemy = NULL; - m_pMyEnt->maxspeed = 16.0f; - m_pMyEnt->health = 100; m_pMyEnt->armour = 50; - m_pMyEnt->pitch = 0; - m_pMyEnt->roll = 0; - m_pMyEnt->state = CS_ALIVE; - m_pMyEnt->anger = 0; m_pMyEnt->pBot = this; - m_pMyEnt->lastanimswitchtime = -1; -// loopi(NUMGUNS) m_pMyEnt->ammo[i] = m_pMyEnt->mag[i] = 0; /* UNDONE m_pMyEnt->ammo[GUN_FIST] = 1; @@ -135,7 +123,7 @@ void CACBot::Spawn() ResetWaypointVars(); } -void CACBot::BotPain(int damage, dynent *d, bool gib) +void CACBot::BotPain(int damage, playerent *d, bool gib) { if(m_pMyEnt->state!=CS_ALIVE || editmode || intermission) return; //fixmebot @@ -164,8 +152,6 @@ void CACBot::BotPain(int damage, dynent *d, bool gib) addmsg(SV_BOTDIED, "ri3", BotManager.GetBotIndex(m_pMyEnt), -1, false); if(gib) addgib(m_pMyEnt); } - else if (d->monsterstate) - conoutf("%s got killed by %s", m_pMyEnt->name, d->name); else { int KillerIndex = -1; @@ -173,14 +159,14 @@ void CACBot::BotPain(int damage, dynent *d, bool gib) if (d == m_pMyEnt) { conoutf("%s suicided", d->name); - KillerIndex = BotManager.GetBotIndex(d); + KillerIndex = BotManager.GetBotIndex(m_pMyEnt); addmsg(SV_BOTFRAGS, "rii", KillerIndex, --d->frags); } else { - if (d->bIsBot) + if (d->type==ENT_BOT) { - KillerIndex = BotManager.GetBotIndex(d); + KillerIndex = BotManager.GetBotIndex((botent *)d); addmsg(SV_BOTFRAGS, "rii", KillerIndex, ++d->frags); } else @@ -197,7 +183,7 @@ void CACBot::BotPain(int damage, dynent *d, bool gib) } } addmsg(SV_BOTDIED, "ri3", BotManager.GetBotIndex(m_pMyEnt), KillerIndex, - d->bIsBot); + d->type==ENT_BOT); if(d->gunselect==GUN_KNIFE) addgib(m_pMyEnt); } @@ -228,7 +214,7 @@ void CACBot::CheckItemPickup() if ((i < sents.length()) && (!sents[i].spawned)) continue; if(OUTBORD(e.x, e.y)) continue; - vec v = { e.x, e.y, S(e.x, e.y)->floor+m_pMyEnt->eyeheight }; + vec v(e.x, e.y, S(e.x, e.y)->floor+m_pMyEnt->eyeheight); if(v.dist(m_pMyEnt->o)<2.5) { diff --git a/source/src/bot/ac_bot.h b/source/src/bot/ac_bot.h index 6abe9e77..8cce7149 100644 --- a/source/src/bot/ac_bot.h +++ b/source/src/bot/ac_bot.h @@ -36,7 +36,7 @@ public: virtual bool DoSPStuff(void); virtual void Spawn(void); - virtual void BotPain(int damage, dynent *d, bool gib=false); + virtual void BotPain(int damage, playerent *d, bool gib=false); }; inline void AddScreenText(char *t, ...) {}; // UNDONE diff --git a/source/src/bot/ac_bot_ai.cpp b/source/src/bot/ac_bot_ai.cpp index 33b0e910..a339ee75 100644 --- a/source/src/bot/ac_bot_ai.cpp +++ b/source/src/bot/ac_bot_ai.cpp @@ -123,7 +123,7 @@ entity *CACBot::SearchForEnts(bool bUseWPs, float flRange, float flMaxHeight) { sScore = 0; entity &e = ents[i]; - vec o = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }; + vec o(e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight); if (!ents[i].spawned) continue; if (OUTBORD(e.x, e.y)) continue; @@ -247,8 +247,8 @@ bool CACBot::HeadToTargetEnt() { if (m_pTargetEnt) { - vec o = { m_pTargetEnt->x, m_pTargetEnt->y, - S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight }; + vec o(m_pTargetEnt->x, m_pTargetEnt->y, + S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight); if (m_pTargetEnt->spawned && (!UnderWater(m_pMyEnt->o) || !UnderWater(o))) diff --git a/source/src/bot/bot.cpp b/source/src/bot/bot.cpp index e308e166..3eb46344 100644 --- a/source/src/bot/bot.cpp +++ b/source/src/bot/bot.cpp @@ -12,14 +12,14 @@ #include "../cube.h" -dvector bots; +vector bots; extern vector sents; extern int triggertime; extern itemstat itemstats[]; extern ENetHost *clienthost; -const vec g_vecZero = {0,0,0}; +const vec g_vecZero(0, 0, 0); //Bot class begin @@ -39,22 +39,11 @@ CBot::~CBot() void CBot::Spawn() { // Init all bot variabeles - m_pMyEnt->eyeheight = 4.5f; - m_pMyEnt->aboveeye = 0.7f; - m_pMyEnt->radius = 1.1f; - spawnplayer(m_pMyEnt); - m_pMyEnt->targetyaw = m_pMyEnt->yaw = m_pMyEnt->targetpitch = m_pMyEnt->pitch = 0.0f; - m_pMyEnt->move = 0; + m_pMyEnt->targetyaw = m_pMyEnt->targetpitch = 0.0f; m_pMyEnt->enemy = NULL; m_pMyEnt->maxspeed = 22.0f; - m_pMyEnt->health = 100; - m_pMyEnt->armour = 0; - m_pMyEnt->pitch = 0; - m_pMyEnt->roll = 0; - m_pMyEnt->state = CS_ALIVE; - m_pMyEnt->anger = 0; m_pMyEnt->pBot = this; m_eCurrentBotState = STATE_NORMAL; @@ -362,7 +351,7 @@ float CBot::GetDistance(const vec &v1, const vec &v2) float CBot::GetDistance(entity *e) { - vec v = { e->x, e->y, e->z }; + vec v(e->x, e->y, e->z); return v.dist(m_pMyEnt->o); } @@ -376,7 +365,7 @@ bool CBot::SelectGun(int Gun) bool CBot::IsVisible(entity *e, bool CheckPlayers) { - vec v = { e->x, e->y, e->z }; + vec v(e->x, e->y, e->z); return ::IsVisible(m_pMyEnt->o, v, (CheckPlayers) ? m_pMyEnt : NULL); } diff --git a/source/src/bot/bot.h b/source/src/bot/bot.h index feb0b1f3..1084b3c4 100644 --- a/source/src/bot/bot.h +++ b/source/src/bot/bot.h @@ -164,11 +164,11 @@ struct unreachable_ent_s class CBot { public: - dynent *m_pMyEnt; + botent *m_pMyEnt; int m_iLastBotUpdate; // Combat variabels - dynent *m_pPrevEnemy; + playerent *m_pPrevEnemy; int m_iShootDelay; int m_iChangeWeaponDelay; int m_iCombatNavTime; @@ -181,7 +181,7 @@ public: // Hunting variabeles int m_iHuntDelay; vec m_vHuntLocation, m_vPrevHuntLocation; - dynent *m_pHuntTarget; + playerent *m_pHuntTarget; float m_fPrevHuntDist; int m_iHuntPauseTime, m_iHuntPlayerUpdateTime, m_iHuntLastTurnLessTime; int m_iLookAroundDelay, m_iLookAroundTime, m_iLookAroundUpdateTime; @@ -240,14 +240,13 @@ public: virtual void CheckItemPickup(void) = 0; virtual void PickUp(int n) = 0; virtual void AddItem(int i, int &v, int spawnsec, int t) = 0; - virtual void BotPain(int damage, dynent *d, bool gib=false) = 0; + virtual void BotPain(int damage, playerent *d, bool gib=false) = 0; void SendBotInfo(void); float GetDistance(const vec &o); float GetDistance(const vec &v1, const vec &v2); float GetDistance(entity *e); float Get2DDistance(const vec &v) { return ::Get2DDistance(m_pMyEnt->o, v); }; - vec GetViewAngles(void) { vec temp = { m_pMyEnt->pitch, m_pMyEnt->yaw, - m_pMyEnt->roll }; return temp; }; + vec GetViewAngles(void) { return vec(m_pMyEnt->pitch, m_pMyEnt->yaw, m_pMyEnt->roll); }; void ResetMoveSpeed(void) { m_pMyEnt->move = m_pMyEnt->strafe = 0; }; void SetMoveDir(int iMoveDir, bool add); void ResetCurrentTask(); @@ -267,7 +266,7 @@ public: bool IsVisible(const vec &o, bool CheckPlayers = false) { return ::IsVisible(m_pMyEnt->o, o, (CheckPlayers) ? m_pMyEnt : NULL); }; - bool IsVisible(dynent *d, bool CheckPlayers = false) { return ::IsVisible(m_pMyEnt->o, d->o, + bool IsVisible(playerent *d, bool CheckPlayers = false) { return ::IsVisible(m_pMyEnt->o, d->o, (CheckPlayers) ? m_pMyEnt : NULL); }; bool IsVisible(entity *e, bool CheckPlayers = false); @@ -275,7 +274,7 @@ public: bool IsVisible(int Dir, float flDist, bool CheckPlayers) { return IsVisible(m_pMyEnt->o, Dir, flDist, CheckPlayers); }; bool IsInFOV(const vec &o); - bool IsInFOV(dynent *d) { return IsInFOV(d->o); }; + bool IsInFOV(playerent *d) { return IsInFOV(d->o); }; int GetShootDelay(void); virtual bool ChoosePreferredWeapon(void); virtual entity *SearchForEnts(bool bUseWPs, float flRange=9999.0f, @@ -284,7 +283,7 @@ public: bool CheckItems(void); bool InUnreachableList(entity *e); virtual bool DoSPStuff(void) = 0; - vec GetEnemyPos(dynent *d); + vec GetEnemyPos(playerent *d); bool AStar(void); float AStarCost(waypoint_s *pWP1, waypoint_s *pWP2); void CleanAStarLists(bool bPathFailed); @@ -328,7 +327,7 @@ public: class CStoredBot; -extern dvector bots; +extern vector bots; class CBotManager { @@ -363,7 +362,7 @@ class CBotManager friend class CWaypointClass; public: - dynent *m_pBotToView; + botent *m_pBotToView; // Construction CBotManager(void) { m_bInit = true; m_fReAddBotDelay = -1.0f; }; @@ -379,7 +378,7 @@ public: void RespawnBots(void) { loopv(bots) if (bots[i] && bots[i]->pBot) bots[i]->pBot->Spawn(); }; void EndMap(void); void BeginMap(char *szMapName); - int GetBotIndex(dynent *m); + int GetBotIndex(botent *m); void LetBotsUpdateStats(void); void LetBotsHear(int n, vec *loc); void AddWaypoint(node_s *pNode); @@ -388,10 +387,10 @@ public: bool IdleBots(void) { return m_bIdleBots; }; void SetBotsShoot(bool bShoot) { m_bBotsShoot = bShoot; }; void SetIdleBots(bool bIdle) { m_bIdleBots = bIdle; }; - void EnableBotView(dynent *bot) { m_pBotToView = bot; }; + void EnableBotView(botent *bot) { m_pBotToView = bot; }; void DisableBotView(void); - void ChangeBotSkill(short Skill, dynent *bot = NULL); - dynent *CreateBot(const char *team, const char *skill, const char *name); + void ChangeBotSkill(short Skill, botent *bot = NULL); + botent *CreateBot(const char *team, const char *skill, const char *name); void ViewBot(void); void CalculateMaxAStarCount(void); void PickNextTrigger(void); diff --git a/source/src/bot/bot_ai.cpp b/source/src/bot/bot_ai.cpp index 95ab2c2d..ee1d189b 100644 --- a/source/src/bot/bot_ai.cpp +++ b/source/src/bot/bot_ai.cpp @@ -17,7 +17,7 @@ extern vector monsters; extern weaponinfo_s WeaponInfoTable[MAX_WEAPONS]; -vec CBot::GetEnemyPos(dynent *d) +vec CBot::GetEnemyPos(playerent *d) { // Aim offset idea by botman vec o = d->o, offset; @@ -137,7 +137,7 @@ bool CBot::FindEnemy(void) float MaxDelay = m_pBotSkill->flMaxEnemySearchDelay; m_iEnemySearchDelay = lastmillis + int(RandomFloat(MinDelay, MaxDelay) * 1000.0f); - dynent *pNewEnemy = NULL, *d = NULL; + playerent *pNewEnemy = NULL, *d = NULL; float flDist, flNearestDist = 99999.9f; short EnemyVal, BestEnemyVal = -100; @@ -311,7 +311,7 @@ bool CBot::CheckHunt(void) // Add enemy hunt search delay m_iHuntDelay = lastmillis + 1500; - dynent *pNewEnemy = NULL, *d = NULL; + playerent *pNewEnemy = NULL, *d = NULL; float flDist, flNearestDist = 99999.9f, flNearestOldPosDistToEnemy = 99999.9f; float flNearestOldPosDistToBot = 99999.9f; short EnemyVal, BestEnemyVal = -100; @@ -1226,8 +1226,8 @@ void CBot::DoCombatNav() if (m_pTargetEnt) { // Bot has already found an entity, still valid? - vec v = { m_pTargetEnt->x, m_pTargetEnt->y, - S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight }; + vec v(m_pTargetEnt->x, m_pTargetEnt->y, + S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight); if ((GetDistance(v) > 25.0f) || !IsVisible(m_pTargetEnt)) m_pTargetEnt = NULL; } @@ -1247,8 +1247,8 @@ void CBot::DoCombatNav() if (m_pTargetEnt) { condebug("Combat ent"); - vec v = { m_pTargetEnt->x, m_pTargetEnt->y, - S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight }; + vec v(m_pTargetEnt->x, m_pTargetEnt->y, + S(m_pTargetEnt->x, m_pTargetEnt->y)->floor+m_pMyEnt->eyeheight); debugbeam(m_pMyEnt->o, v); @@ -1763,7 +1763,7 @@ void CBot::CheckFOV() { m_iCheckEnvDelay = lastmillis + RandomLong(125, 250); vec MyAngles = GetViewAngles(); - vec src, forward, right, up, dest, best = {0,0,0}; + vec src, forward, right, up, dest, best(0, 0, 0); vec origin = m_pMyEnt->o; float flDist, flFurthestDist = 0; bool WallLeft = false; @@ -1884,7 +1884,7 @@ void CBot::CheckFOV() //sqr *s = S(fast_f2nat(x), fast_f2nat(y)); //if (!SOLID(s)) { - vec from = { x, y, m_pMyEnt->o.z }; + vec from(x, y, m_pMyEnt->o.z); dest = from; dest.z -= 6.0f; TraceLine(from, dest, m_pMyEnt, false, &tr); @@ -1968,7 +1968,7 @@ bool CBot::WaterNav() if (SOLID(s)) continue; if ((x==cx) && (y==cy)) continue; - vec v = { x, y, GetCubeFloor(x, y) }; + vec v(x, y, GetCubeFloor(x, y)); if (UnderWater(v)) continue; // Skip, cube is underwater @@ -1982,7 +1982,7 @@ bool CBot::WaterNav() for (int b=(y-2);b<=(y+2);b++) { if ((x==a) && (y==b)) continue; - vec v2 = { a, b, GetCubeFloor(a, b) }; + vec v2(a, b, GetCubeFloor(a, b)); if (v.z < (v2.z-1-JUMP_HEIGHT)) { small=true; @@ -2212,7 +2212,7 @@ void CBot::HearSound(int n, vec *o) // Look who made the sound(check for the nearest enemy) float flDist, flNearestDist = 3.0f; // Range of 3 units - dynent *pNearest = NULL; + playerent *pNearest = NULL; /* edit -argh if (m_sp) diff --git a/source/src/bot/bot_util.cpp b/source/src/bot/bot_util.cpp index 383eabb9..ea76c39b 100644 --- a/source/src/bot/bot_util.cpp +++ b/source/src/bot/bot_util.cpp @@ -24,8 +24,6 @@ #include #endif -extern dvector monsters; - // Function code by PMB - Begin @@ -251,24 +249,6 @@ void TraceLine(vec from, vec to, dynent *pTracer, bool CheckPlayers, traceresult } } - // Check if the 'line' collides with monsters - /* we don't have monsters anymore, thanks for the bots :) -argh - dvector &mv = getmonsters(); - loopv(mv) - { - dynent *d = mv[i]; - if(!d || (d==pTracer) || (d->state != CS_ALIVE)) continue; // Only check valid monsters - - flDist = GetDistance(from, d->o); - - if ((flDist < flNearestDist) && (intersect(d, from, to, &tr->end))) - { - flNearestDist = flDist; - tr->collided = true; - } - } - */ - // Check if the 'line' collides with the local player(player1) dynent *d = player1; // Shortcut @@ -445,7 +425,7 @@ float GetYawDiff(float curyaw, vec v1, vec v2) vec CrossProduct(const vec &a, const vec &b) { - vec cross = { a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x }; + vec cross(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); return cross; } @@ -511,18 +491,7 @@ bool IsInGame(dynent *d) { if (!d) return false; - /*edit -argh - if (d->monsterstate) - { - loopv(monsters) - { - if (monsters[i] == d) - return true; - } - } - */ - //else - if (d->bIsBot) + if (d->type==ENT_BOT) { loopv(bots) { diff --git a/source/src/bot/bot_waypoint.cpp b/source/src/bot/bot_waypoint.cpp index 672a67c6..07a11fbc 100644 --- a/source/src/bot/bot_waypoint.cpp +++ b/source/src/bot/bot_waypoint.cpp @@ -704,7 +704,7 @@ void CWaypointClass::DrawNearWaypoints() // Has this waypoint an target yaw? if (pNearest->sYaw != -1) { - vec angles = { 0, pNearest->sYaw, 0 }; + vec angles(0, pNearest->sYaw, 0); vec from = pNearest->v_origin, end = pNearest->v_origin; vec forward, right, up; @@ -1190,7 +1190,7 @@ void CWaypointClass::CalcCost(node_s *pNode) { if (OUTBORD(a, b)) continue; - vec to = { a, b, GetCubeFloor(a, b) + 1.0f }; + vec to(a, b, GetCubeFloor(a, b) + 1.0f); // See if there is a obstacle(cube or mapmodel) nearby traceresult_s tr; @@ -1218,7 +1218,7 @@ void CWaypointClass::CalcCost(node_s *pNode) { if (OUTBORD(a, b)) continue; - vec to = { a, b, GetCubeFloor(a, b) + 1.0f }; + vec to(a, b, GetCubeFloor(a, b) + 1.0f); // See if there is a obstacle(cube or mapmodel) nearby traceresult_s tr; @@ -1299,7 +1299,7 @@ void CWaypointClass::FloodThink() for (y=MINBORD; y<(ssize-MINBORD); y+=4) { - vec from = { x, y, GetCubeFloor(x, y)+2.0f }; + vec from(x, y, GetCubeFloor(x, y)+2.0f); bool bFound = CanPlaceNodeHere(from); if (!bFound) diff --git a/source/src/bot/botmanager.cpp b/source/src/bot/botmanager.cpp index 153deb02..ddb1a4e3 100644 --- a/source/src/bot/botmanager.cpp +++ b/source/src/bot/botmanager.cpp @@ -14,7 +14,7 @@ #ifndef VANILLA_CUBE // UNDONE bool dedserv = false; -#define CS_DEDHOST -1 +#define CS_DEDHOST 0xFF #endif extern ENetHost *clienthost; @@ -315,7 +315,7 @@ char *CBotManager::GetBotTeam() return szOutput; } -extern void renderplayer(dynent *d); +extern void renderplayer(playerent *d); void CBotManager::RenderBots() { @@ -352,7 +352,7 @@ void CBotManager::EndMap() } bots[i]->pBot = NULL; - zapdynent(bots[i]); + DELETEP(bots[i]); } bots.setsize(0); condebug("Cleared all bots"); @@ -377,7 +377,7 @@ void CBotManager::BeginMap(char *szMapName) PickNextTrigger(); } -int CBotManager::GetBotIndex(dynent *m) +int CBotManager::GetBotIndex(botent *m) { loopv(bots) { @@ -784,7 +784,7 @@ void CBotManager::InitSkillData() m_BotSkills[4].bCanSearchItemsInCombat = false; } -void CBotManager::ChangeBotSkill(short Skill, dynent *bot) +void CBotManager::ChangeBotSkill(short Skill, botent *bot) { static char *SkillNames[5] = { "best", "good", "medium", "worse", "bad" }; @@ -881,7 +881,7 @@ void CBotManager::PickNextTrigger() #endif if (OUTBORD(e.x, e.y)) continue; - vec o = { e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight }; + vec o(e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight); node_s *pWptNearEnt = NULL; @@ -915,9 +915,9 @@ void CBotManager::PickNextTrigger() m_sCurrentTriggerNr = lowest; } -dynent *CBotManager::CreateBot(const char *team, const char *skill, const char *name) +botent *CBotManager::CreateBot(const char *team, const char *skill, const char *name) { - dynent *m = newdynent(); + botent *m = newbotent(); if (!m) return NULL; loopi(NUMGUNS) m->ammo[i] = m->mag[i] = 0; // Create new bot class, dependand on the current mod @@ -928,7 +928,7 @@ dynent *CBotManager::CreateBot(const char *team, const char *skill, const char * #else #error "Unsupported mod!" #endif - m->bIsBot = true; + m->type = ENT_BOT; m->pBot->m_pMyEnt = m; m->pBot->m_iLastBotUpdate = 0; m->pBot->m_bSendC2SInit = false; @@ -993,7 +993,7 @@ void addbot(char *arg1, char *arg2, char *arg3) if (ishost()) { conoutf("Creating bot...\n"); - dynent *b = BotManager.CreateBot(arg1, arg2, arg3); + botent *b = BotManager.CreateBot(arg1, arg2, arg3); if (b) conoutf("connected: %s", b->name); else @@ -1155,7 +1155,7 @@ void kickbot(const char *szName) if(bots[iBotInd]->name[0]) conoutf("bot %s disconnected", bots[iBotInd]->name); delete bots[iBotInd]->pBot; - zapdynent(bots[iBotInd]); + DELETEP(bots[iBotInd]); bots.remove(iBotInd); } else if (clienthost) // Ask server to destroy bot(with voting) @@ -1189,7 +1189,7 @@ void kickallbots(void) conoutf("bot %s disconnected",(bots[i]->name[0] ? bots[i]->name : "[incompatible client]")); delete bots[i]->pBot; - zapdynent(bots[i]); + DELETEP(bots[i]); } else if (clienthost) // Ask the server to destroy all bots { @@ -1336,7 +1336,7 @@ COMMAND(drawbeamtoteleporters, ARG_NONE); void telebot(void) { vec dest = player1->o, forward, right, up; - vec angles = { player1->pitch, player1->yaw, player1->roll }; + vec angles(player1->pitch, player1->yaw, player1->roll); traceresult_s tr; AnglesToVectors(angles, forward, right, up); diff --git a/source/src/client.cpp b/source/src/client.cpp index c3fcf639..b0f22612 100644 --- a/source/src/client.cpp +++ b/source/src/client.cpp @@ -129,7 +129,7 @@ void disconnect(int onlyclean, int async) clientnum = -1; c2sinit = false; player1->lifesequence = 0; - loopv(players) zapdynent(players[i]); + loopv(players) zapplayer(players[i]); localdisconnect(); diff --git a/source/src/clientextras.cpp b/source/src/clientextras.cpp index a163b1ef..ae5744b7 100644 --- a/source/src/clientextras.cpp +++ b/source/src/clientextras.cpp @@ -2,85 +2,64 @@ #include "cube.h" -// render players & monsters -// very messy ad-hoc handling of animation frames, should be made more configurable -// idle, run, attack, pain, jump, land, flipoff, salute, taunt, wave, point, crouch idle, crouch walk, crouch attack, crouch pain, crouch death, death, lying dead -// I R A P P P J L F S T W P CI CW CA CP CD D D D LD LD LD -int frame[] = { 0, 40, 46, 54, 58, 62, 66, 69, 72, 84, 95, 112,123,135,154,160,169,173,178,184,190,183,189,197 }; -int range[] = { 40, 5, 8, 4, 4, 4, 3, 3, 12, 11, 17, 11, 13, 19, 6, 9, 4, 5, 6, 6, 8, 1, 1, 1 }; - -// D D D D' D D D D' A A' P P' I I' R, R' Q L J J' -/*int frame[] = { 178, 184, 190, 137, 183, 189, 197, 164, 46, 51, 54, 32, 0, 0, 40, 1, 154, 162, 67, 168 }; -int range[] = { 6, 6, 8, 28, 1, 1, 1, 1, 8, 19, 4, 18, 40, 1, 6, 15, 6, 1, 1, 1 };*/ - -VAR(die,0,0,1); - -void renderclient(dynent *d, bool team, char *mdlname, float scale) +void renderclient(playerent *d, char *mdlname, char *vwepname) { - int n = 3; - int oldaniminterpt = -1; + int varseed = (int)(size_t)d; + int anim = ANIM_PAIN; float speed = 100.0f; - float mz = d->o.z-d->eyeheight+1.55f*scale; + float mz = d->o.z-d->eyeheight; int basetime = -((int)(size_t)d&0xFFF); if(d->state==CS_DEAD) { - loopv(physents) if(physents[i]->state==GIB && physents[i]->owner==d) return; + loopv(bounceents) if(bounceents[i]->bouncestate==GIB && bounceents[i]->owner==d) return; d->pitch = 0.1f; - int r; - n = (d->lastaction%3)+18; - r = range[n]; + int r = 6; + anim = ANIM_DEATH; + varseed += d->lastaction; basetime = d->lastaction; int t = lastmillis-d->lastaction; if(t<0 || t>20000) return; if(t>(r-1)*100-50) { - n += 3; + anim = ANIM_LYING_DEAD|ANIM_NOINTERP; if(t>(r+10)*100) { t -= (r+10)*100; mz -= t*t/10000000000.0f*t; }; - oldaniminterpt = getvar("animationinterpolationtime"); // disable anim interp. temporarly - setvar("animationinterpolationtime", 0); }; //if(mz<-1000) return; } - else if(d->state==CS_EDITING) { n = 8; } - else if(d->state==CS_LAGGED) { n = 13; } - else if((!d->move && !d->strafe) /*|| !d->moving*/) { n = 0; } - else if(!d->onfloor && d->timeinair>100) { n = 6; } - else { n = 1; speed = 1200/d->maxspeed*scale; }; - rendermodel(mdlname, frame[n], range[n], 0, 1.5f, d->o.x, mz, d->o.y, d->yaw+90, d->pitch/4, team, scale, speed, 0, basetime, true, d); - if(oldaniminterpt!=-1) setvar("animationinterpolationtime", oldaniminterpt); + else if(d->state==CS_EDITING) { anim = ANIM_TAUNT|ANIM_LOOP; } + else if(d->state==CS_LAGGED) { anim = ANIM_CROUCH_ATTACK|ANIM_LOOP; } + else if(!d->move && !d->strafe) { anim = ANIM_IDLE|ANIM_LOOP; } + else if(!d->onfloor && d->timeinair>100) { anim = ANIM_JUMP; } + else { anim = ANIM_RUN|ANIM_LOOP; speed = 1860/d->maxspeed; }; + rendermodel(mdlname, anim, 0, 1.5f, d->o.x, mz, d->o.y, d->yaw+90, d->pitch/4, speed, basetime, d, vwepname); }; extern int democlientnum; -void renderplayer(dynent *d) +void renderplayer(playerent *d) { if(!d) return; int team = rb_team_int(d->team); s_sprintfd(mdl)("playermodels/%s/0%i", team==TEAM_CLA ? "terrorist" : "counterterrorist", 1 + max(0, min(d->skin, (team==TEAM_CLA ? 3 : 5)))); - renderclient(d, isteam(player1->team, d->team), mdl, 1.55f); - - if(d->gunselect>=0 && d->gunselectgunselect]); - renderclient(d, isteam(player1->team, d->team), vwep, 1.55f); - }; -} + string vwep; + if(d->gunselect>=0 && d->gunselectgunselect]); + else vwep[0] = 0; + renderclient(d, mdl, vwep[0] ? vwep : NULL); +}; void renderclients() { - dynent *d; - loopv(players) - if((d = players[i]) && (!demoplayback || i!=democlientnum)) + playerent *d; + loopv(players) if((d = players[i]) && (!demoplayback || i!=democlientnum)) { if(strcmp(d->name, "dummy") == 0) { d->gunselect = player1->gunselect; - d->moving = true; d->health != 1 ? d->state=CS_ALIVE : d->state=CS_DEAD; }; renderplayer(d); @@ -104,7 +83,7 @@ struct sline { string s; }; vector scorelines; int menu = 0; -void renderscore(dynent *d) +void renderscore(playerent *d) { s_sprintfd(lag)("%d", d->plag); s_sprintfd(name) ("(%s)", d->name); @@ -119,7 +98,7 @@ int teamscore[maxteams], teamflagscore[maxteams], teamsused; // EDIT: AH string teamscores; int timeremain = 0; -void addteamscore(dynent *d) +void addteamscore(playerent *d) { if(!d) return; loopi(teamsused) if(strcmp(teamname[i], d->team)==0) diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index de8bd7af..addedae3 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -15,8 +15,8 @@ COMMAND(mode, ARG_1INT); bool intermission = false; -dynent *player1 = newdynent(); // our client -dvector players; // other clients +playerent *player1 = newplayerent(); // our client +vector players; // other clients VAR(sensitivity, 0, 10, 1000); VAR(sensitivityscale, 1, 1, 100); @@ -30,36 +30,13 @@ extern int framesinmap; char *getclientmap() { return clientmap; }; -void resetmovement(dynent *d) -{ - d->k_left = false; - d->k_right = false; - d->k_up = false; - d->k_down = false; - d->jumpnext = false; - d->strafe = 0; - d->move = 0; -}; - extern bool c2sinit; extern int dblend; -void spawnstate(dynent *d) // reset player state not persistent accross spawns +void spawnstate(playerent *d) // reset player state not persistent accross spawns { - resetmovement(d); - d->vel.x = d->vel.y = d->vel.z = 0; - d->onfloor = false; - d->timeinair = 0; - d->health = 100; - d->armour = 0; - //d->hasarmour = false; - //d->armourtype = A_BLUE; - d->akimbomillis = 0; - d->gunselect = GUN_PISTOL; - d->gunwait = 0; - d->attacking = false; + d->respawn(); d->lastaction = lastmillis; - d->weaponchanging = false; if(d==player1) { gun_changed = true; @@ -73,54 +50,26 @@ void spawnstate(dynent *d) // reset player state not persistent acc }; radd(d); dblend = 0; - d->akimbo = false; }; -dynent *newdynent() // create a new blank player or monster +playerent *newplayerent() // create a new blank player { - dynent *d = new dynent; - d->o.x = 0; - d->o.y = 0; - d->o.z = 0; - d->yaw = 270; - d->pitch = 0; - d->roll = 0; - d->maxspeed = 16; //16 max speed, 14 max with armour - d->outsidemap = false; - d->inwater = false; - d->radius = 1.1f; - d->eyeheight = 4.5f; //4.25f; - d->aboveeye = 0.7f; - d->frags = 0; - d->flagscore = 0; // EDIT: AH - d->plag = 0; - d->ping = 0; + playerent *d = new playerent; d->lastupdate = lastmillis; - d->enemy = NULL; - d->monsterstate = 0; - d->name[0] = d->team[0] = 0; - d->blocked = false; - d->lifesequence = 0; - d->state = CS_ALIVE; - d->shots = 0; - d->reloading = false; - d->primary = d->nextprimary = GUN_ASSAULT; - d->hasarmour = false; - d->gunselect = GUN_PISTOL; - d->onladder = false; - d->isphysent = false; - d->inhandnade = NULL; - d->skin = d->nextskin = 0; - d->bIsBot = false; - d->pBot = NULL; - d->weaponchanging = false; - d->lastanimswitchtime = -1; - loopi(NUMGUNS) d->ammo[i] = d->mag[i] = 0; d->skin = rnd(1 + rb_team_int(d->team) == TEAM_CLA ? 3 : 5); spawnstate(d); return d; }; +botent *newbotent() // create a new blank player +{ + botent *d = new botent; + d->lastupdate = lastmillis; + d->skin = rnd(1 + rb_team_int(d->team) == TEAM_CLA ? 3 : 5); + spawnstate(d); + return d; +}; + void ctf_death() // EDIT: AH { int flag = rb_opposite(rb_team_int(player1->team)); @@ -151,7 +100,7 @@ void respawn() }; }; -void arenacount(dynent *d, int &alive, int &dead, char *&lastteam, char *&lastname, bool &oneteam) +void arenacount(playerent *d, int &alive, int &dead, char *&lastteam, char *&lastname, bool &oneteam) { if(d->state!=CS_DEAD) { @@ -183,7 +132,7 @@ void arenarespawn() // Added by Rick: Let all bots respawn if were the host if (ishost()) BotManager.RespawnBots(); //End add by Rick - clearphysents(); + clearbounceents(); }; } else if(arenadetectwait==0 || arenadetectwait=0) shoot(player1, worldpos); // only shoot when connected to server gets2c(); // do this first, so we have most accurate information when our player moves }; - mphysents(); + mbounceents(); otherplayers(); if(!demoplayback) { @@ -322,7 +271,7 @@ void updateworld(int curtime, int lastmillis) // main game update loop }; }; -void entinmap(dynent *d) // brute force but effective way to find a free spawn spot in the map +void entinmap(physent *d) // brute force but effective way to find a free spawn spot in the map { loopi(100) // try max 100 times { @@ -347,10 +296,10 @@ int nearestenemy(vec *v, string team) float nearestPlayerDistSquared = -1; loopv(players) { - dynent *other = players[i]; + playerent *other = players[i]; if(!other) continue; if(isteam(team,other->team))continue; // its a teammate - vec place = {v->x, v->y, v->z}; + vec place(v->x, v->y, v->z); float distsquared = vec(other->o).sub(place).squaredlen(); if(nearestPlayerDistSquared == -1) nearestPlayerDistSquared = distsquared; // first run else if(distsquared < nearestPlayerDistSquared) nearestPlayerDistSquared = distsquared; // if a player is closer @@ -362,7 +311,7 @@ int nearestenemy(vec *v, string team) int spawncycle = -1; int fixspawn = 2; -void spawnplayer(dynent *d, bool secure) // place at random spawn +void spawnplayer(playerent *d, bool secure) // place at random spawn { loopj(10) // EDIT: AH { @@ -371,7 +320,7 @@ void spawnplayer(dynent *d, bool secure) // place at random spawn if(spawncycle!=-1 && secure) { entity &e = ents[spawncycle]; - vec pos = { e.x, e.y, e.z }; + vec pos(e.x, e.y, e.z); if(nearestenemy(&pos, d->team) == -1) break; } else break; }; @@ -441,7 +390,7 @@ void mousemove(int dx, int dy) // damage arriving from the network, monsters, yourself, all ends up here. -void selfdamage(int damage, int actor, dynent *act, bool gib) +void selfdamage(int damage, int actor, playerent *act, bool gib) { if(!act) return; if(player1->state!=CS_ALIVE || editmode || intermission) return; @@ -469,8 +418,8 @@ void selfdamage(int damage, int actor, dynent *act, bool gib) { // Modified by Rick //dynent *a = getclient(actor); - dynent *a; - if(act->bIsBot) a = act; + playerent *a; + if(act->type==ENT_BOT) a = act; else a = getclient(actor); // End mod @@ -490,7 +439,7 @@ void selfdamage(int damage, int actor, dynent *act, bool gib) if(m_ctf) ctf_death(); showscores(true); setscope(false); - if(act->bIsBot) addmsg(SV_DIEDBYBOT, "ri", actor); + if(act->type==ENT_BOT) addmsg(SV_DIEDBYBOT, "ri", actor); else addmsg(gib ? SV_GIBDIED : SV_DIED, "ri", actor); player1->lifesequence++; player1->attacking = false; @@ -503,7 +452,7 @@ void selfdamage(int damage, int actor, dynent *act, bool gib) spawnstate(player1); //player1->lastaction = lastmillis; //fixme - if (act->bIsBot) addmsg(SV_BOTFRAGS, "rii", BotManager.GetBotIndex(act), ++act->frags); + if (act->type==ENT_BOT) addmsg(SV_BOTFRAGS, "rii", BotManager.GetBotIndex((botent *)act), ++act->frags); } else { @@ -528,7 +477,7 @@ void timeupdate(int timeremain) }; }; -dynent *getclient(int cn) // ensure valid entity +playerent *getclient(int cn) // ensure valid entity { if(cn<0 || cn>=MAXCLIENTS) { @@ -536,11 +485,11 @@ dynent *getclient(int cn) // ensure valid entity return NULL; }; while(cn>=players.length()) players.add(NULL); - return players[cn] ? players[cn] : (players[cn] = newdynent()); + return players[cn] ? players[cn] : (players[cn] = newplayerent()); }; // Added by Rick -dynent *getbot(int cn) // ensure valid entity +botent *getbot(int cn) // ensure valid entity { if(cn<0 || cn>=MAXCLIENTS) { @@ -551,11 +500,11 @@ dynent *getbot(int cn) // ensure valid entity while(cn>=bots.length()) bots.add(NULL); if (!bots[cn]) { - bots[cn] = newdynent(); + bots[cn] = newbotent(); if (bots[cn]) { bots[cn]->pBot = NULL; - bots[cn]->bIsBot = true; + bots[cn]->type = ENT_BOT; } } @@ -624,7 +573,7 @@ void startmap(char *name) // called just after a map load intermission = false; framesinmap = 0; conoutf("game mode is %s", modestr(gamemode)); - clearphysents(); + clearbounceents(); }; COMMANDN(map, changemap, ARG_1STR); diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 1bbe2171..01d3a705 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -51,7 +51,7 @@ void botcommand(ucharbuf &p, char *text) // don't care if he's in the scenery or other players, // just don't overlap with our client -void updatepos(dynent *d) +void updatepos(playerent *d) { const float r = player1->radius+d->radius; const float dx = player1->o.x-d->o.x; @@ -80,7 +80,7 @@ extern void trydisconnect(); void parsepositions(ucharbuf &p) { int cn = -1, type; - dynent *d = NULL; + playerent *d = NULL; while(p.remaining()) switch(type = getint(p)) { case SV_POS: // position of another client @@ -112,7 +112,7 @@ void parsepositions(ucharbuf &p) case SV_BOTUPDATE: { int n = getint(p); - dynent *b = getbot(n); + botent *b = getbot(n); if(!b) return; b->o.x = getint(p)/DMF; b->o.y = getint(p)/DMF; @@ -132,8 +132,7 @@ void parsepositions(ucharbuf &p) if(state==CS_DEAD && b->state!=CS_DEAD) b->lastaction = lastmillis; b->state = state; - if (!b->bIsBot) - b->bIsBot = true; + if (!b->type!=ENT_BOT) b->type = ENT_BOT; if(!demoplayback) updatepos(b); break; @@ -145,7 +144,7 @@ void parsepositions(ucharbuf &p) }; }; -void parsemessages(int cn, dynent *d, ucharbuf &p) +void parsemessages(int cn, playerent *d, ucharbuf &p) { static char text[MAXTRANS]; int type; @@ -240,7 +239,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) int cn = getint(p); if(!(d = getclient(cn))) break; if(d->name[0]) conoutf("player %s disconnected", d->name); - zapdynent(players[cn]); + zapplayer(players[cn]); break; }; @@ -281,7 +280,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) if(target==clientnum) { - dynent *a = getbot(damager); + botent *a = getbot(damager); if(ls==player1->lifesequence) selfdamage(damage, cn, a); } @@ -320,7 +319,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) } else { - dynent *a = killedbybot ? getbot(actor) : getclient(actor); + playerent *a = killedbybot ? getbot(actor) : getclient(actor); if(a) { if(isteam(a->team, d->name)) @@ -350,7 +349,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) case SV_RESUME: { int cn = getint(p), frags = getint(p), flags = getint(p); - dynent *d = cn==clientnum ? player1 : getclient(cn); + playerent *d = cn==clientnum ? player1 : getclient(cn); if(d) { d->frags = frags; @@ -519,7 +518,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) case SV_BOTSOUND: { int Sound = getint(p); - dynent *pBot = getbot(getint(p)); + botent *pBot = getbot(getint(p)); if (pBot) playsound(Sound, &pBot->o); @@ -529,7 +528,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) case SV_ADDBOT: // Bot joined the game { - dynent *b = getbot(getint(p)); + botent *b = getbot(getint(p)); if (!b) break; getstring(text, p); @@ -547,7 +546,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) getstring(text, p); s_strcpy(b->team, text); b->lifesequence = getint(p); - b->bIsBot = true; + b->type = ENT_BOT; b->pBot = NULL; break; }; @@ -555,14 +554,14 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) case SV_BOTDIS: { int n = getint(p); - dynent *b = getbot(n); + botent *b = getbot(n); if (!b) break; if(b->name[0]) conoutf("bot %s disconnected", b->name); delete b->pBot; - zapdynent(bots[n]); + DELETEP(bots[n]); bots.remove(n); break; } @@ -573,9 +572,9 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) int target = getint(p); int damage = getint(p); int damager = getint(p); - dynent *b = getbot(target); + botent *b = getbot(target); - dynent *a; + playerent *a; if (damager == -1) { // HACK! if the local client who sended the message is the damager, its -1 @@ -603,7 +602,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) int b = getint(p); int killer = getint(p); bool KilledByABot = getint(p) > 0; //fixmebot - dynent *bot = getbot(b); + botent *bot = getbot(b); if((b==killer) && KilledByABot) { @@ -628,7 +627,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) } else { - dynent *k; + playerent *k; if (KilledByABot) k = getbot(killer); else if (killer == -1) @@ -657,7 +656,7 @@ void parsemessages(int cn, dynent *d, ucharbuf &p) case SV_BOTFRAGS: { - dynent *b = getbot(getint(p)); + botent *b = getbot(getint(p)); if (b) b->frags = getint(p); break; }; @@ -693,7 +692,7 @@ void localservertoclient(int chan, uchar *buf, int len) // processes any updat while(p.remaining()) { int cn = p.get(); - dynent *d = getclient(cn); + playerent *d = getclient(cn); int len = p.get(); len += p.get()<<8; ucharbuf q(&p.buf[p.len], min(len, p.maxlen-p.len)); diff --git a/source/src/command.cpp b/source/src/command.cpp index 06d77db2..78289b39 100644 --- a/source/src/command.cpp +++ b/source/src/command.cpp @@ -166,6 +166,7 @@ int execute(char *p) // all evaluation happens here, case ARG_1STR: ((void (__cdecl *)(char *))id->fun)(w[1]); break; case ARG_2STR: ((void (__cdecl *)(char *, char *))id->fun)(w[1], w[2]); break; case ARG_3STR: ((void (__cdecl *)(char *, char *, char*))id->fun)(w[1], w[2], w[3]); break; + case ARG_4STR: ((void (__cdecl *)(char *, char *, char*, char*))id->fun)(w[1], w[2], w[3], w[4]); break; case ARG_5STR: ((void (__cdecl *)(char *, char *, char*, char*, char*))id->fun)(w[1], w[2], w[3], w[4], w[5]); break; case ARG_6STR: ((void (__cdecl *)(char *, char *, char*, char*, char*, char*))id->fun)(w[1], w[2], w[3], w[4], w[5], w[6]); break; case ARG_DOWN: ((void (__cdecl *)(bool))id->fun)(addreleaseaction(id->name)!=NULL); break; diff --git a/source/src/cube.h b/source/src/cube.h index 75a4615c..ec787e23 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -141,7 +141,18 @@ struct header // map file format header struct vec { - float x, y, z; + union + { + struct { float x, y, z; }; + float v[3]; + }; + + vec() {}; + vec(float a, float b, float c) : x(a), y(b), z(c) {}; + vec(float *v) : x(v[0]), y(v[1]), z(v[2]) {}; + + float &operator[](int i) { return v[i]; }; + float operator[](int i) const { return v[i]; }; bool operator==(const vec &o) const { return x == o.x && y == o.y && z == o.z; } bool operator!=(const vec &o) const { return x != o.x || y != o.y || z != o.z; } @@ -167,7 +178,6 @@ struct vec }; struct block { int x, y, xs, ys; }; -struct mapmodelinfo { int rad, h, zoff, snap; char *name; }; enum { GUN_KNIFE = 0, GUN_PISTOL, GUN_SHOTGUN, GUN_SUBGUN, GUN_SNIPER, GUN_ASSAULT, GUN_GRENADE, NUMGUNS }; enum { G_PRIMARY=0, G_SECONDARY, G_MELEE, G_GRENADE, G_NUM }; @@ -211,75 +221,110 @@ struct itemstat { int add, start, max, sound; }; // End add -struct md2state +enum { ANIM_IDLE = 0, ANIM_RUN, ANIM_ATTACK, ANIM_PAIN, ANIM_JUMP, ANIM_LAND, ANIM_FLIPOFF, ANIM_SALUTE, ANIM_TAUNT, ANIM_WAVE, ANIM_POINT, ANIM_CROUCH_IDLE, ANIM_CROUCH_WALK, ANIM_CROUCH_ATTACK, ANIM_CROUCH_PAIN, ANIM_CROUCH_DEATH, ANIM_DEATH, ANIM_LYING_DEAD, ANIM_FLAG, ANIM_GUN_IDLE, ANIM_GUN_SHOOT, ANIM_GUN_RELOAD, ANIM_GUN_THROW, ANIM_MAPMODEL, ANIM_TRIGGER, ANIM_ALL, NUMANIMS }; + +#define ANIM_INDEX 0xFF +#define ANIM_LOOP (1<<8) +#define ANIM_START (1<<9) +#define ANIM_END (1<<10) +#define ANIM_REVERSE (1<<11) +#define ANIM_NOINTERP (1<<12) +#define ANIM_MIRROR (1<<13) + +struct animstate // used for animation blending of animated characters { int anim, frame, range, basetime; float speed; - //md2state() : anim(0), frame(0), range(0), basetime(0), speed(100.0f) { }; - md2state() - { - anim = frame = range = basetime = 0; - speed = 100.0f; - } + animstate() : anim(0), frame(0), range(0), basetime(0), speed(100.0f) { }; - bool operator==(const md2state &o) const { return frame==o.frame && range==o.range && basetime==o.basetime && speed==o.speed; }; - bool operator!=(const md2state &o) const { return frame!=o.frame || range!=o.range || basetime!=o.basetime || speed!=o.speed; }; + bool operator==(const animstate &o) const { return frame==o.frame && range==o.range && basetime==o.basetime && speed==o.speed; }; + bool operator!=(const animstate &o) const { return frame!=o.frame || range!=o.range || basetime!=o.basetime || speed!=o.speed; }; }; +enum { MDL_MD2 = 1, MDL_MD3 }; -struct md3state -{ - int anim; - int frm; - int lastTime; +struct dynent; + +struct model +{ + float scale; + vec translate; + + model() : scale(1), translate(0, 0, 0) {}; + virtual ~model() {}; + virtual void render(int anim, int varseed, float speed, int basetime, float x, float y, float z, float yaw, float pitch, dynent *d, model *vwepmdl = NULL, float scale = 1.0f) = 0; + virtual void setskin(int tex = 0) = 0; + virtual bool load() = 0; + virtual char *name() = 0; + virtual int type() = 0; }; -enum // md3 animations -{ - BOTH_DEATH1 = 0, - BOTH_DEAD1, - BOTH_DEATH2, - BOTH_DEAD2, - BOTH_DEATH3, - BOTH_DEAD3, - TORSO_GESTURE, - TORSO_ATTACK, - TORSO_ATTACK2, - TORSO_DROP, - TORSO_RAISE, - TORSO_STAND, - TORSO_STAND2, - LEGS_WALKCR, - LEGS_WALK, - LEGS_RUN, - LEGS_BACK, - LEGS_SWIM, - LEGS_JUMP, - LEGS_LAND, - LEGS_JUMPB, - LEGS_LANDB, - LEGS_IDLE, - LEGS_IDLECR, - LEGS_TURN -}; +struct mapmodelinfo { int rad, h, zoff; string name; model *m; }; -struct dynent // players & monsters +enum { ENT_PLAYER = 0, ENT_BOT, ENT_BOUNCE }; + +enum { CS_ALIVE = 0, CS_DEAD, CS_LAGGED, CS_EDITING }; + +struct physent { vec o, vel; // origin, velocity float yaw, pitch, roll; // used as vec in one place - float oldpitch; float maxspeed; // cubes per second, 24 for player - bool outsidemap; // from his eyes - bool inwater; - bool onfloor, jumpnext; - int move, strafe; - bool k_left, k_right, k_up, k_down; // see input code int timeinair; // used for fake gravity + int gravity; float radius, eyeheight, aboveeye; // bounding box size + bool inwater; + bool onfloor, onladder, jumpnext; + char move, strafe; + uchar state, type; + + physent() : o(0, 0, 0), yaw(270), pitch(0), roll(0), maxspeed(16), gravity(20), + radius(1.1f), eyeheight(4.5f), aboveeye(0.7f), + state(CS_ALIVE), type(ENT_PLAYER) + { + reset(); + }; + + void reset() + { + vel.x = vel.y = vel.z = 0; + move = strafe = 0; + timeinair = 0; + onfloor = onladder = inwater = false; + }; +}; + +struct dynent : physent // animated ent +{ + bool k_left, k_right, k_up, k_down; // see input code + + animstate prev[2], current[2]; // md2's need only [0], md3's need both for the lower&upper model + int lastanimswitchtime[2]; + void *lastmodel[2]; + + void stopmoving() + { + k_left = k_right = k_up = k_down = jumpnext = false; + move = strafe = 0; + }; + + void reset() + { + physent::reset(); + stopmoving(); + }; + + dynent() { reset(); loopi(2) { lastanimswitchtime[i] = -1; lastmodel[i] = NULL; }; }; +}; + +struct bounceent; + +struct playerent : dynent +{ + float oldpitch; int lastupdate, plag, ping; int lifesequence; // sequence id for each respawn, used in damage test - int state; // one of CS_* below - int frags; + int frags, flagscore; int health, armour; //armourtype, quadmillis; int akimbomillis; int gunselect, gunwait; @@ -287,18 +332,6 @@ struct dynent // players & monsters bool attacking; int ammo[NUMGUNS]; int mag[NUMGUNS]; - int monsterstate; // one of M_* below, M_NONE means human - int mtype; // see monster.cpp - dynent *enemy; // monster wants to kill this entity - // Added by Rick: targetpitch - float targetpitch; // monster wants to look in this direction - // End add - float targetyaw; // monster wants to look in this direction - bool blocked, moving; // used by physics to signal ai - int trigger; // millis at which transition to another monsterstate takes place - vec attacktarget; // delayed attacks - int anger; // how many times already hit by fellow monster - int flagscore; // EDIT: AH string name, team; //int startheight; int shots; //keeps track of shots from auto weapons @@ -307,28 +340,55 @@ struct dynent // players & monsters int primary; //primary gun int nextprimary; // primary after respawning int skin, nextskin; // skin after respawning - md3state animstate[3]; - int lastanimswitchtime; - md2state current, prev; - int attackmillis; - - bool onladder; - int gravity; - bool isphysent; // hack - + int thrownademillis; - struct physent *inhandnade; + struct bounceent *inhandnade; int akimbo; int akimbolastaction[2]; - float rotspeed; - + + CPrevLocation PrevLocations; // Previous stored locations of this player + + playerent() : plag(0), ping(0), lifesequence(0), frags(0), flagscore(0), + shots(0), reloading(false), primary(GUN_ASSAULT), nextprimary(GUN_ASSAULT), + skin(0), nextskin(0), inhandnade(NULL) + { + name[0] = team[0] = 0; + respawn(); + }; + + void respawn() + { + reset(); + health = 100; + armour = 0; + hasarmour = false; + //armourtype = A_BLUE; + akimbomillis = 0; + gunselect = GUN_PISTOL; + gunwait = 0; + attacking = false; + weaponchanging = false; + akimbo = false; + loopi(NUMGUNS) ammo[i] = mag[i] = 0; + }; +}; + +struct botent : playerent +{ // Added by Rick CBot *pBot; // Only used if this is a bot, points to the bot class if we are the host, // for other clients its NULL - bool bIsBot; // Is this dynent a bot? - CPrevLocation PrevLocations; // Previous stored locations of this player // End add by Rick + + playerent *enemy; // monster wants to kill this entity + // Added by Rick: targetpitch + float targetpitch; // monster wants to look in this direction + // End add + float targetyaw; // monster wants to look in this direction + + botent() : pBot(NULL), enemy(NULL) { type = ENT_BOT; }; }; + // Moved from server.cpp by Rick struct server_entity // server side version of "entity" type { @@ -343,19 +403,29 @@ enum { CTFF_INBASE = 0, CTFF_STOLEN, CTFF_DROPPED }; struct flaginfo { entity *flag; - dynent *actor; + playerent *actor; vec originalpos; int state; // one of the types above bool pick_ack; flaginfo() : flag(0), actor(0), state(CTFF_INBASE), pick_ack(false) {}; }; -enum { PHYSENT_NONE = 0, NADE_ACTIVATED, NADE_THROWED, GIB}; +enum { NADE_ACTIVATED = 1, NADE_THROWED, GIB}; -struct physent : dynent // nades, gibs +struct bounceent : physent // nades, gibs { - int millis, timetolife, state; // see enum above - dynent *owner; + int millis, timetolife, bouncestate; // see enum above + float rotspeed; + playerent *owner; + + bounceent() : bouncestate(0), rotspeed(1.0f), owner(NULL) + { + type = ENT_BOUNCE; + maxspeed = 40; + radius = 0.2f; + eyeheight = 0.3f; + aboveeye = 0.0f; + }; }; #define NADE_IN_HAND (player1->gunselect==GUN_GRENADE && player1->inhandnade) @@ -366,7 +436,6 @@ struct physent : dynent // nades, gibs #define SAVEGAMEVERSION 6 // bump if dynent/netprotocol changes or any other savegame/demo data bumped from 5 //enum { A_BLUE, A_GREEN, A_YELLOW }; // armour types... take 20/40/60 % off -enum { M_NONE = 0, M_SEARCH, M_HOME, M_ATTACKING, M_PAIN, M_SLEEP, M_AIMING, M_NADE /* bloody hack*/ }; // monster states #define MAXCLIENTS 256 // in a multiplayer game, can be arbitrarily changed #define MAXTRANS 5000 // max amount of data to swallow in 1 go @@ -399,8 +468,6 @@ enum SV_EXT, }; -enum { CS_ALIVE = 0, CS_DEAD, CS_LAGGED, CS_EDITING }; - // hardcoded sounds, defined in sounds.cfg enum { @@ -429,7 +496,6 @@ enum struct vertex { float u, v, x, y, z; uchar r, g, b, a; }; -typedef vector dvector; typedef vector cvector; typedef vector ivector; @@ -439,9 +505,9 @@ extern sqr *world, *wmip[]; // map data, the mips are sequential 2D extern header hdr; // current map header extern int sfactor, ssize; // ssize = 2^sfactor extern int cubicsize, mipsize; // cubicsize = ssize^2 -extern dynent *player1; // special client ent that receives input and acts as camera -extern dvector players; // all the other clients (in multiplayer) -extern vectorphysents; +extern playerent *player1; // special client ent that receives input and acts as camera +extern vector players; // all the other clients (in multiplayer) +extern vector bounceents; extern bool editmode; extern vector ents; // map entities extern vec worldpos; // current target of the crosshair in the world @@ -501,7 +567,7 @@ enum // function signatures for script functions, see command.cpp { ARG_1INT, ARG_2INT, ARG_3INT, ARG_4INT, ARG_NONE, - ARG_1STR, ARG_2STR, ARG_3STR, ARG_5STR, ARG_6STR, + ARG_1STR, ARG_2STR, ARG_3STR, ARG_4STR, ARG_5STR, ARG_6STR, ARG_DOWN, ARG_1EXP, ARG_2EXP, ARG_1EST, ARG_2EST, @@ -523,8 +589,8 @@ extern ENetHost *clienthost; inline bool ishost(void) { return !clienthost; }; void splaysound(int n, vec *loc=0); -void addteamscore(dynent *d); -void renderscore(dynent *d); +void addteamscore(playerent *d); +void renderscore(playerent *d); extern void conoutf(const char *s, ...); // Moved from protos.h extern void particle_trail(int type, int fade, vec &from, vec &to); // Moved from protos.h extern bool listenserv; diff --git a/source/src/entities.cpp b/source/src/entities.cpp index 807e6cb5..5c9a6c2a 100644 --- a/source/src/entities.cpp +++ b/source/src/entities.cpp @@ -12,13 +12,20 @@ char *entmdlnames[] = int triggertime = 0; -void renderent(entity &e, char *mdlname, float z, float yaw, int frame = 0, int numf = 1, int basetime = 0, float speed = 10.0f) +void renderent(entity &e, char *mdlname, float z, float yaw, int anim = ANIM_MAPMODEL|ANIM_LOOP, int basetime = 0, float speed = 10.0f) { - rendermodel(mdlname, frame, numf, 0, 1.1f, e.x, z+S(e.x, e.y)->floor, e.y, yaw, 0, false, 1.0f, speed, 0, basetime); + rendermodel(mdlname, anim, 0, 1.1f, e.x, z+S(e.x, e.y)->floor, e.y, yaw, 0, speed, basetime); }; extern void newparticle(vec &o, vec &d, int fade, int type, int tex = -1); +int triggeranim(entity &e) +{ + int anim = ANIM_TRIGGER; + if(!triggertime) anim |= e.spawned ? ANIM_START : ANIM_END; + return anim; +}; + void renderentities() { if(lastmillis>triggertime+1000) triggertime = 0; @@ -29,7 +36,7 @@ void renderentities() { mapmodelinfo &mmi = getmminfo(e.attr2); if(!&mmi) continue; - rendermodel(mmi.name, 0, 1, e.attr4, (float)mmi.rad, e.x, (float)S(e.x, e.y)->floor+mmi.zoff+e.attr3, e.y, (float)((e.attr1+7)-(e.attr1+7)%15), 0, false, 1.0f, 10.0f, mmi.snap); + rendermodel(mmi.name, ANIM_MAPMODEL|ANIM_LOOP, e.attr4, (float)mmi.rad, e.x, (float)S(e.x, e.y)->floor+mmi.zoff+e.attr3, e.y, (float)((e.attr1+7)-(e.attr1+7)%15), 0, 10.0f); } else if(e.type==CTF_FLAG && m_ctf) // EDIT: AH { @@ -38,14 +45,12 @@ void renderentities() { if(f.actor == player1) continue; s_sprintfd(path)("pickups/flags/small_%s", rb_team_string(e.attr2)); - mapmodelinfo mmi = {10, 4, 0, 0, path}; - rendermodel(mmi.name, 0, 1, 0, 0, f.actor->o.x, f.actor->o.z+0.3f+(sin(lastmillis/100.0f)+1)/10, f.actor->o.y, lastmillis/2.5f, 0, false, 0.6f, 120.0f, mmi.snap); + rendermodel(path, ANIM_FLAG|ANIM_START, 0, 0, f.actor->o.x, f.actor->o.z+0.3f+(sin(lastmillis/100.0f)+1)/10, f.actor->o.y, lastmillis/2.5f, 0, 120.0f); } else { s_sprintfd(path)("pickups/flags/%s", rb_team_string(e.attr2)); - mapmodelinfo mmi = {10, 4, 0, 0, path}; - rendermodel(mmi.name, 0, 7, 0, (float)mmi.rad, e.x, f.state==CTFF_INBASE ? (float)S(e.x, e.y)->floor : e.z, e.y, (float)((e.attr1+7)-(e.attr1+7)%15), 0, false, 1.0f, 120.0f, mmi.snap); + rendermodel(path, ANIM_FLAG|ANIM_LOOP, 0, 4, e.x, f.state==CTFF_INBASE ? (float)S(e.x, e.y)->floor : e.z, e.y, (float)((e.attr1+7)-(e.attr1+7)%15), 0, 120.0f); }; } else @@ -69,8 +74,8 @@ void renderentities() renderent(e, "carrot", (float)(1+sin(lastmillis/100.0+e.x+e.y)/20), lastmillis/(e.attr2 ? 1.0f : 10.0f)); break; - case 4: renderent(e, "switch2", 3, (float)e.attr3*90, (!e.spawned && !triggertime) ? 1 : 0, (e.spawned || !triggertime) ? 1 : 2, triggertime, 1050.0f); break; - case 5: renderent(e, "switch1", -0.15f, (float)e.attr3*90, (!e.spawned && !triggertime) ? 30 : 0, (e.spawned || !triggertime) ? 1 : 30, triggertime, 35.0f); break; + case 4: renderent(e, "switch2", 3, (float)e.attr3*90, triggeranim(e), triggertime); break; + case 5: renderent(e, "switch1", -0.15f, (float)e.attr3*90, triggeranim(e), triggertime); break; }; }; }; @@ -92,7 +97,7 @@ itemstat itemstats[] = void baseammo(int gun) { player1->ammo[gun] = itemstats[gun].add*2; }; // Added by Rick: baseammo for bots -void botbaseammo(int gun, dynent *d) { d->ammo[gun] = itemstats[gun].add*2; }; +void botbaseammo(int gun, playerent *d) { d->ammo[gun] = itemstats[gun].add*2; }; // End add // these two functions are called when the server acknowledges that you really @@ -109,7 +114,7 @@ void radditem(int i, int &v, int t) extern void weapon(int gun); -void realpickup(int n, dynent *d) +void realpickup(int n, playerent *d) { switch(ents[n].type) { @@ -150,7 +155,7 @@ void additem(int i, int &v, int spawnsec, int t) }; }; -void pickup(int n, dynent *d) +void pickup(int n, playerent *d) { int np = 1; loopv(players) if(players[i]) np++; @@ -224,7 +229,7 @@ void checkitems() if(e.type==LADDER) { if(OUTBORD(e.x, e.y)) continue; - vec v = { e.x, e.y, player1->o.z }; + vec v(e.x, e.y, player1->o.z); float dist1 = player1->o.dist(v); float dist2 = player1->o.z - (S(e.x, e.y)->floor+player1->eyeheight); if(dist1<1.5f && dist2floor+player1->eyeheight }; + vec v(e.x, e.y, S(e.x, e.y)->floor+player1->eyeheight); if(player1->o.dist(v)<2.5f) pickup(i, player1); }; }; @@ -262,7 +267,7 @@ void resetspawns() }; void setspawn(int i, bool on) { if(i=0) ents[i].spawned = on; }; -void radd(dynent *d) +void radd(playerent *d) { loopi(NUMGUNS) if(d->nextprimary!=i) d->ammo[i] = 0; @@ -314,7 +319,7 @@ bool intersect(entity *e, vec &from, vec &to, vec *end) // if lineseg hits entit float lo = (float)(S(e->x, e->y)->floor+mmi.zoff+e->attr3); float hi = lo+mmi.h; - vec v = to, w = { e->x, e->y, lo + (fabs(hi-lo)/2.0f) }, *p; + vec v = to, w(e->x, e->y, lo + (fabs(hi-lo)/2.0f)), *p; v.sub(from); w.sub(from); float c1 = w.dot(v); diff --git a/source/src/hudgun.cpp b/source/src/hudgun.cpp new file mode 100644 index 00000000..dd251cc5 --- /dev/null +++ b/source/src/hudgun.cpp @@ -0,0 +1,130 @@ +#include "cube.h" + +VAR(swayspeeddiv, 1, 125, 1000); +VAR(swaymovediv, 1, 200, 1000); + +VAR(swayupspeeddiv, 1, 125, 1000); +VAR(swayupmovediv, 1, 200, 1000); + +VAR(x, 0, 0, 1000); +VAR(y, 0, 0, 1000); +VAR(z, 0, 0, 1000); + +struct weaponmove +{ + float k_rot, kick; + vec pos; + int anim; + + weaponmove() : k_rot(0), kick(0), anim(0) { pos.x = pos.y = pos.z = 0.0f; }; + + void calcmove(vec base, int basetime) + { + int timediff = NADE_THROWING ? (lastmillis-player1->thrownademillis) : lastmillis-basetime; + int animtime = attackdelay(player1->gunselect); + int rtime = reloadtime(player1->gunselect); + + kick = k_rot = 0.0f; + pos = player1->o; + anim = ANIM_GUN_IDLE; + + if(player1->weaponchanging) + { + anim = ANIM_GUN_RELOAD; + float percent_done = (float)(timediff)*100.0f/(float) WEAPONCHANGE_TIME; + if(percent_done>=100 || percent_done<0) percent_done = 100; + k_rot = -(sin((float)(percent_done*2/100.0f*90.0f)*PI/180.0f)*90); + } + else if(player1->reloading) + { + anim = ANIM_GUN_RELOAD; + float percent_done = (float)(timediff)*100.0f/(float)rtime; + if(percent_done>=100 || percent_done<0) percent_done = 100; + k_rot = -(sin((float)(percent_done*2/100.0f*90.0f)*PI/180.0f)*90); + } + else + { + vec sway = base; + float percent_done = 0.0f; + float k_back = 0.0f; + + if(player1->gunselect==player1->lastattackgun) + { + percent_done = timediff*100.0f/(float)animtime; + if(percent_done > 100.0f) percent_done = 100.0f; + // f(x) = -sin(x-1.5)^3 + kick = -sin(pow((1.5f/100.0f*percent_done)-1.5f,3)); + }; + + if(player1->lastaction && player1->lastattackgun==player1->gunselect) + { + if(NADE_THROWING && timedifflastactiongunselect!=GUN_KNIFE && player1->gunselect!=GUN_GRENADE ? ANIM_LOOP : 0); + }; + + if(player1->gunselect!=GUN_GRENADE && player1->gunselect!=GUN_KNIFE) + { + k_rot = kick_rot(player1->gunselect)*kick; + k_back = kick_back(player1->gunselect)*kick/10; + }; + + float swayspeed = (float) (sin((float)lastmillis/swayspeeddiv))/(swaymovediv/10.0f); + float swayupspeed = (float) (sin((float)lastmillis/swayupspeeddiv-90))/(swayupmovediv/10.0f); + + #define g0(x) ((x) < 0.0f ? -(x) : (x)) + float plspeed = min(1.0f, sqrt(g0(player1->vel.x*player1->vel.x) + g0(player1->vel.y*player1->vel.y))); + + swayspeed *= plspeed/2; + swayupspeed *= plspeed/2; + + float tmp = sway.x; + sway.x = sway.y; + sway.y = -tmp; + + if(swayupspeed<0.0f)swayupspeed = -swayupspeed; // sway a semicirle only + sway.z = 1.0f; + + sway.x *= swayspeed; + sway.y *= swayspeed; + sway.z *= swayupspeed; + + pos.x = player1->o.x-base.x*k_back+sway.x; + pos.y = player1->o.y-base.y*k_back+sway.y; + pos.z = player1->o.z-base.z*k_back+sway.z; + }; + }; +}; + +void renderhudgun(int gun, int lastaction, int index = 0) +{ + vec unitv; + float dist = worldpos.dist(player1->o, unitv); + unitv.div(dist); + + weaponmove wm; + if(!intermission) wm.calcmove(unitv, lastaction); + s_sprintfd(path)("weapons/%s", hudgunnames[gun]); + static int lastanim[2], lastswitch[2]; + if(lastanim[index]!=wm.anim|(gun<<16)) + { + lastanim[index] = wm.anim|(gun<<16); + lastswitch[index] = lastmillis; + }; + rendermodel(path, wm.anim|(index ? ANIM_MIRROR : 0), 0, 0, wm.pos.x, wm.pos.z, wm.pos.y, player1->yaw + 90, player1->pitch+wm.k_rot, 40.0f, lastswitch[index]); +}; + +void renderhudgun() +{ + if(player1->akimbo && player1->gunselect==GUN_PISTOL) // akimbo + { + renderhudgun(GUN_PISTOL, player1->akimbolastaction[0]); + renderhudgun(GUN_PISTOL, player1->akimbolastaction[1], true); + } + else + { + renderhudgun(player1->gunselect, player1->lastaction); + }; +}; + + diff --git a/source/src/main.cpp b/source/src/main.cpp index fdd9a089..38342f0f 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -323,9 +323,6 @@ int main(int argc, char **argv) exec("config/servers.cfg"); exec("config/autoexec.cfg"); - log("base models"); - loadweapons(); - log("localconnect"); localconnect(); changemap("maps/ac_complex"); diff --git a/source/src/md2.h b/source/src/md2.h new file mode 100644 index 00000000..d9d11d8d --- /dev/null +++ b/source/src/md2.h @@ -0,0 +1,234 @@ +struct md2; + +md2 *loadingmd2 = 0; + +static inline bool htcmp(const vertmodel::tcvert &x, const vertmodel::tcvert &y) +{ + return x.u==y.u && x.v==y.v && x.index==y.index; +}; + +static inline uint hthash(const vertmodel::tcvert &x) +{ + return x.index; +}; + +struct md2 : vertmodel +{ + struct md2_header + { + int magic; + int version; + int skinwidth, skinheight; + int framesize; + int numskins, numvertices, numtexcoords; + int numtriangles, numglcommands, numframes; + int offsetskins, offsettexcoords, offsettriangles; + int offsetframes, offsetglcommands, offsetend; + }; + + struct md2_vertex + { + uchar vertex[3], normalindex; + }; + + struct md2_frame + { + float scale[3]; + float translate[3]; + char name[16]; + }; + + md2(const char *name) : vertmodel(name) {}; + + int type() { return MDL_MD2; }; + + struct md2part : part + { + void gentcverts(int *glcommands, vector &tcverts, vector &tris) + { + hashtable tchash; + vector idxs; + for(int *command = glcommands; (*command)!=0;) + { + int numvertex = *command++; + bool isfan; + if(isfan = (numvertex<0)) numvertex = -numvertex; + idxs.setsizenodelete(0); + loopi(numvertex) + { + union { int i; float f; } u, v; + u.i = *command++; + v.i = *command++; + tcvert tckey = { u.f, v.f, (ushort)*command++ }; + int *idx = tchash.access(tckey); + if(!idx) + { + idx = &tchash[tckey]; + *idx = tcverts.length(); + tcverts.add(tckey); + }; + idxs.add(*idx); + }; + loopi(numvertex-2) + { + tri &t = tris.add(); + if(isfan) + { + t.vert[0] = idxs[0]; + t.vert[1] = idxs[i+1]; + t.vert[2] = idxs[i+2]; + } + else loopk(3) t.vert[k] = idxs[i&1 && k ? i+(1-(k-1))+1 : i+k]; + }; + }; + }; + + bool load(char *filename) + { + if(loaded) return true; + FILE *file = fopen(filename, "rb"); + if(!file) return false; + + md2_header header; + fread(&header, sizeof(md2_header), 1, file); + endianswap(&header, sizeof(int), sizeof(md2_header)/sizeof(int)); + + if(header.magic!=844121161 || header.version!=8) + { + fclose(file); + return false; + }; + + numframes = header.numframes; + + mesh &m = *new mesh; + meshes.add(&m); + + int *glcommands = new int[header.numglcommands]; + fseek(file, header.offsetglcommands, SEEK_SET); + fread(glcommands, header.numglcommands*sizeof(int), 1, file); + endianswap(glcommands, sizeof(int), header.numglcommands); + + vector tcgen; + vector trigen; + gentcverts(glcommands, tcgen, trigen); + delete[] glcommands; + + m.numtcverts = tcgen.length(); + m.tcverts = new tcvert[m.numtcverts]; + memcpy(m.tcverts, tcgen.getbuf(), m.numtcverts*sizeof(tcvert)); + m.numtris = trigen.length(); + m.tris = new tri[m.numtris]; + memcpy(m.tris, trigen.getbuf(), m.numtris*sizeof(tri)); + + m.numverts = header.numvertices; + m.verts = new vec[m.numverts*numframes]; + + int frame_offset = header.offsetframes; + vec *curvert = m.verts; + loopi(header.numframes) + { + md2_frame frame; + fseek(file, frame_offset, SEEK_SET); + fread(&frame, sizeof(md2_frame), 1, file); + endianswap(&frame, sizeof(float), 6); + loopj(header.numvertices) + { + md2_vertex v; + fread(&v, sizeof(md2_vertex), 1, file); + *curvert++ = vec(v.vertex[0]*frame.scale[0]+frame.translate[0], + v.vertex[2]*frame.scale[2]+frame.translate[2], + -(v.vertex[1]*frame.scale[1]+frame.translate[1])); + }; + frame_offset += header.framesize; + }; + + fclose(file); + + return loaded = true; + }; + + void getdefaultanim(animstate &as, int anim, int varseed, float speed) + { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 21 23 24 + // I R A P P P J L F S T W P CI CW CA CP CD D D D LD LD LD F + static int frame[] = { 0, 40, 46, 54, 58, 62, 66, 69, 72, 84, 95, 112,123,135,154,160,169,173,178,184,190,183,189,197, 0 }; + static int range[] = { 40, 5, 8, 4, 4, 4, 3, 3, 12, 11, 17, 11, 13, 19, 6, 9, 4, 5, 6, 6, 8, 1, 1, 1, 7 }; + static int animfr[] = { 0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 24 }; + + as.speed = speed; + if((size_t)anim >= sizeof(animfr)/sizeof(animfr[0])) + { + as.frame = 0; + as.range = 1; + return; + }; + int n = animfr[anim]; + if(anim==ANIM_PAIN || anim==ANIM_DEATH || anim==ANIM_LYING_DEAD) n += varseed%3; + as.frame = frame[n]; + as.range = range[n]; + }; + }; + + void render(int anim, int varseed, float speed, int basetime, float x, float y, float z, float yaw, float pitch, dynent *d, model *vwepmdl, float scale) + { + if(!loaded) return; + + glPushMatrix(); + glTranslatef(x, y, z); + glRotatef(yaw+180, 0, -1, 0); + glRotatef(pitch, 0, 0, 1); + parts[0]->render(anim, varseed, speed, basetime, d, scale); + glPopMatrix(); + + if(vwepmdl) + { + ((md2 *)vwepmdl)->parts[0]->index = parts.length(); + vwepmdl->setskin(); + vwepmdl->render(anim, varseed, speed, basetime, x, y, z, yaw, pitch, d, NULL, scale); + }; + }; + + bool load() + { + if(loaded) return true; + md2part &mdl = *new md2part; + parts.add(&mdl); + mdl.model = this; + mdl.index = 0; + char *pname = parentdir(loadname); + s_sprintfd(name1)("packages/models/%s/tris.md2", loadname); + if(!mdl.load(path(name1))) + { + s_sprintf(name1)("packages/models/%s/tris.md2", pname); // try md2 in parent folder (vert sharing) + if(!mdl.load(path(name1))) { delete[] pname; return false; }; + }; + Texture *skin; + loadskin(loadname, pname, skin, this); + loopv(mdl.meshes) mdl.meshes[i]->skin = skin; + if(skin==crosshair) conoutf("could not load model skin for %s", name1); + loadingmd2 = this; + s_sprintfd(name3)("packages/models/%s/md2.cfg", loadname); + if(!execfile(name3)) + { + s_sprintf(name3)("packages/models/%s/md2.cfg", pname); + execfile(name3); + }; + delete[] pname; + loadingmd2 = 0; + loopv(parts) parts[i]->scaleverts(scale/16.0f, vec(translate.x, translate.z, -translate.y)); + return loaded = true; + }; +}; + +void md2anim(char *anim, char *frame, char *range, char *s) +{ + if(!loadingmd2 || loadingmd2->parts.empty()) { conoutf("not loading an md2"); return; }; + int num = findanim(anim); + if(num<0) { conoutf("could not find animation %s", anim); return; }; + float speed = s[0] ? atof(s) : 100.0f; + loadingmd2->parts.last()->setanim(num, atoi(frame), atoi(range), speed); +}; + +COMMAND(md2anim, ARG_4STR); + diff --git a/source/src/md3.h b/source/src/md3.h new file mode 100644 index 00000000..03b88385 --- /dev/null +++ b/source/src/md3.h @@ -0,0 +1,250 @@ +struct md3; + +md3 *loadingmd3 = NULL; + +string md3dir; + +struct md3tag +{ + char name[64]; + vec pos; + float rotation[3][3]; +}; + +struct md3vertex +{ + short vertex[3]; + short normal; +}; + +struct md3triangle +{ + int vertexindices[3]; +}; + +struct md3header +{ + char id[4]; + int version; + char name[64]; + int flags; + int numframes, numtags, nummeshes, numskins; + int ofs_frames, ofs_tags, ofs_meshes, ofs_eof; // offsets +}; + +struct md3meshheader +{ + char id[4]; + char name[64]; + int flags; + int numframes, numshaders, numvertices, numtriangles; + int ofs_triangles, ofs_shaders, ofs_uv, ofs_vertices, meshsize; // offsets +}; + +struct md3 : vertmodel +{ + md3(const char *name) : vertmodel(name) {}; + + int type() { return MDL_MD3; }; + + struct md3part : part + { + bool load(char *path) + { + if(loaded) return true; + FILE *f = fopen(path, "rb"); + if(!f) return false; + md3header header; + fread(&header, sizeof(md3header), 1, f); + endianswap(&header.version, sizeof(int), 1); + endianswap(&header.flags, sizeof(int), 9); + if(strncmp(header.id, "IDP3", 4) != 0 || header.version != 15) // header check + { + fclose(f); + conoutf("md3: corrupted header"); + return false; + }; + + numframes = header.numframes; + numtags = header.numtags; + if(numtags) + { + tags = new tag[numframes*numtags]; + fseek(f, header.ofs_tags, SEEK_SET); + md3tag tag; + + loopi(header.numframes*header.numtags) + { + fread(&tag, sizeof(md3tag), 1, f); + endianswap(&tag.pos, sizeof(float), 12); + if(tag.name[0] && iparts[0]; + if(link(vwep, "tag_weapon")) vwep->index = parts.length(); + }; + + glPushMatrix(); + glTranslatef(x, y, z); + glRotatef(yaw+180, 0, -1, 0); + glRotatef(pitch, 0, 0, 1); + glRotatef(-90, 0, 1, 0); + glRotatef(-90, 1, 0, 0); + parts[0]->render(anim, varseed, speed, basetime, d, scale); + glPopMatrix(); + }; + + bool load() + { + if(loaded) return true; + s_sprintf(md3dir)("packages/models/%s", loadname); + + char *pname = parentdir(loadname); + s_sprintfd(cfgname)("packages/models/%s/md3.cfg", loadname); + + loadingmd3 = this; + if(execfile(cfgname)) // configured md3, will call the md3* commands below + { + delete[] pname; + loadingmd3 = NULL; + if(parts.empty()) return false; + loopv(parts) if(!parts[i]->loaded) return false; + } + else // md3 without configuration, try default tris and skin + { + loadingmd3 = NULL; + md3part &mdl = *new md3part; + parts.add(&mdl); + mdl.model = this; + mdl.index = 0; + s_sprintfd(name1)("packages/models/%s/tris.md3", loadname); + if(!mdl.load(path(name1))) + { + s_sprintf(name1)("packages/models/%s/tris.md3", pname); // try md3 in parent folder (vert sharing) + if(!mdl.load(path(name1))) { delete[] pname; return false; }; + }; + Texture *skin; + loadskin(loadname, pname, skin, this); + loopv(mdl.meshes) mdl.meshes[i]->skin = skin; + if(skin==crosshair) conoutf("could not load model skin for %s", name1); + }; + loopv(parts) parts[i]->scaleverts(scale/16.0f, vec(translate.x, translate.y, translate.z)); + + return loaded = true; + }; +}; + +void md3load(char *model) +{ + if(!loadingmd3) { conoutf("not loading an md3"); return; }; + s_sprintfd(filename)("%s/%s", md3dir, model); + md3::md3part &mdl = *new md3::md3part; + loadingmd3->parts.add(&mdl); + mdl.model = loadingmd3; + mdl.index = loadingmd3->parts.length()-1; + if(!mdl.load(path(filename))) conoutf("could not load %s", filename); // ignore failure +}; + +void md3skin(char *objname, char *skin) +{ + if(!objname || !skin) return; + if(!loadingmd3 || loadingmd3->parts.empty()) { conoutf("not loading an md3"); return; }; + md3::part &mdl = *loadingmd3->parts.last(); + loopv(mdl.meshes) + { + md3::mesh &m = *mdl.meshes[i]; + if(!strcmp(m.name, objname)) + { + s_sprintfd(spath)("%s/%s", md3dir, skin); + m.skin = textureload(spath); + }; + }; +}; + +void md3anim(char *anim, char *startframe, char *range, char *s) +{ + if(!loadingmd3 || loadingmd3->parts.empty()) { conoutf("not loading an md3"); return; }; + float speed = s[0] ? atof(s) : 100.0f; + int num = findanim(anim); + if(num<0) { conoutf("could not find animation %s", anim); return; }; + loadingmd3->parts.last()->setanim(num, atoi(startframe), atoi(range), speed); +}; + +void md3link(char *parentno, char *childno, char *tagname) +{ + if(!loadingmd3) { conoutf("not loading an md3"); return; }; + int parent = atoi(parentno), child = atoi(childno); + if(max(parent, child) >= loadingmd3->parts.length() || min(parent, child) < 0) { conoutf("no models loaded to link"); return; }; + if(!loadingmd3->parts[parent]->link(loadingmd3->parts[child], tagname)) conoutf("could not link model %s", loadingmd3->loadname); +}; + +COMMAND(md3load, ARG_1STR); +COMMAND(md3skin, ARG_3STR); +COMMAND(md3anim, ARG_4STR); +COMMAND(md3link, ARG_3STR); + diff --git a/source/src/menus.cpp b/source/src/menus.cpp index fef9ea92..edff8a8f 100644 --- a/source/src/menus.cpp +++ b/source/src/menus.cpp @@ -13,7 +13,7 @@ struct gmenu int mwidth; int menusel; char *mdl; // (optional) md2 mdl - int frame, range, rotspeed, scale; + int anim, rotspeed, scale; }; vector menus; @@ -24,7 +24,7 @@ ivector menustack; void menuset(int menu) // EDIT: AH { - if((vmenu = menu)>=1 && menu != 2) resetmovement(player1); + if((vmenu = menu)>=1 && menu != 2) player1->stopmoving(); if(vmenu==1) menus[1].menusel = 0; }; @@ -76,7 +76,7 @@ bool rendermenu() int y = (VIRTH-h)/2; int x = (VIRTW-w)/2; static Texture *menutex = NULL; - if(!menutex) menutex = textureload("packages/textures/makke/menu.jpg", false, true); + if(!menutex) menutex = textureload("packages/textures/makke/menu.jpg", false); blendbox(x-FONTH/2*3, y-FONTH, x+w+FONTH/2*3, y+h+FONTH, true, menutex->id); draw_text(title, x, y); y += FONTH*2; @@ -117,29 +117,16 @@ void rendermenumdl() glRotatef(player1->yaw+90+180, 0, -1, 0); glRotatef(player1->pitch, 0, 0, 1); - vec pos = { 0.0f, 0.0f, 0.0f }; bool isplayermodel = !strncmp(m.mdl, "playermodels", strlen("playermodels")); - if(isplayermodel) - { - glTranslatef(2.0f, 1.0f, 1.5f); - pos.z = -1.0f; - } - else - { - glTranslatef(2.0f, 1.7f, 0); - }; + vec pos; + if(isplayermodel) pos = vec(2.0f, 1.2f, -0.4f); + else pos = vec(2.0f, 0, 1.7f); - if(m.rotspeed) glRotatef(lastmillis/5.0f/100.0f*m.rotspeed, 0, 1, 0); - rendermodel(m.mdl, m.frame, m.range, 0, 0.0f, pos.x, pos.z, pos.y, 0, 0, false, (float)(m.scale ? m.scale/25.0f : 1.0f), 100, 0, 0, false); - - if(isplayermodel) - { - string vwep; - s_strcpy(vwep, "weapons/subgun/world"); - path(vwep); - rendermodel(vwep, m.frame, m.range, 0, 0.0f, pos.x, pos.z, pos.y, 0, 0, false, (float)(m.scale ? m.scale/25.0f : 1.0f), 100, 0, 0, false); - }; + float yaw = 1.0f; + if(m.rotspeed) yaw += lastmillis/5.0f/100.0f*m.rotspeed; + + rendermodel(m.mdl, m.anim, 0, 0, pos.x, pos.z, pos.y, yaw, 0, 100, 0, NULL, isplayermodel ? (char*)"weapons/subgun/world" : NULL, m.scale ? m.scale/25.0f : 1.0f); glPopMatrix(); } @@ -175,18 +162,17 @@ void menuitem(char *text, char *action, char *hoveraction) mi.hoveraction = hoveraction[0] ? newstring(hoveraction) : NULL; }; -void menumdl(char *mdl, char *frame, char *range, char *rotspeed, char *scale) +void menumdl(char *mdl, char *anim, char *rotspeed, char *scale) { - if(!mdl || !frame || !range) return; + if(!mdl || !anim) return; gmenu &menu = menus.last(); - menu.mdl = newstring(mdl, _MAXDEFSTR); - menu.frame = max(0, atoi(frame)); - menu.range = max(1, atoi(range)); + menu.mdl = newstringbuf(mdl); + menu.anim = findanim(anim)|ANIM_LOOP; menu.rotspeed = max(0, min(atoi(rotspeed), 100)); menu.scale = max(0, min(atoi(scale), 100)); }; -void chmenumdl(char *menu, char *mdl, char *frame, char *range, char *rotspeed, char *scale) +void chmenumdl(char *menu, char *mdl, char *anim, char *rotspeed, char *scale) { if(!menu || !mdl) return; loopv(menus) @@ -195,9 +181,8 @@ void chmenumdl(char *menu, char *mdl, char *frame, char *range, char *rotspeed, if(strcmp(m.name, menu) == 0) { if(m.mdl) s_strcpy(m.mdl, mdl); - else m.mdl = newstring(mdl, _MAXDEFSTR); - m.frame = atoi(frame); - m.range = atoi(range); + else m.mdl = newstringbuf(mdl); + m.anim = findanim(anim)|ANIM_LOOP; m.rotspeed = max(0, min(atoi(rotspeed), 100)); m.scale = max(0, min(atoi(scale), 100)); return; diff --git a/source/src/physics.cpp b/source/src/physics.cpp index ef0164d7..a0ebb13c 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -13,7 +13,6 @@ bool plcollide(dynent *d, dynent *o, float &headspace) // collide with if(fabs(o->o.x-d->o.x)o.y-d->o.y)o.z-d->o.z)aboveeye+d->eyeheight) return false; - if(d->monsterstate) return false; // hack headspace = d->o.z-o->o.z-o->aboveeye-d->eyeheight; if(headspace<0) headspace = 10; }; @@ -21,7 +20,7 @@ bool plcollide(dynent *d, dynent *o, float &headspace) // collide with }; */ -bool plcollide(dynent *d, dynent *o, float &headspace, float &hi, float &lo) // collide with player or monster +bool plcollide(physent *d, physent *o, float &headspace, float &hi, float &lo) // collide with player or monster { if(o->state!=CS_ALIVE) return true; const float r = o->radius+d->radius; @@ -31,7 +30,6 @@ bool plcollide(dynent *d, dynent *o, float &headspace, float &hi, float &lo) else if(o->o.z+o->aboveeye>lo) lo = o->o.z+o->aboveeye+1; if(fabs(o->o.z-d->o.z)aboveeye+d->eyeheight) return false; - //if(d->monsterstate) return false; // hack headspace = d->o.z-o->o.z-o->aboveeye-d->eyeheight; if(headspace<0) headspace = 10; }; @@ -56,7 +54,7 @@ bool cornertest(int mip, int x, int y, int dx, int dy, int &bx, int &by, int &bs return stest; }; -void mmcollide(dynent *d, float &hi, float &lo) // collide with a mapmodel +void mmcollide(physent *d, float &hi, float &lo) // collide with a mapmodel { loopv(ents) { @@ -78,7 +76,7 @@ void mmcollide(dynent *d, float &hi, float &lo) // collide with a mapm // spawn is a dirty side effect used in spawning // drop & rise are supplied by the physics below to indicate gravity/push for current mini-timestep -bool collide(dynent *d, bool spawn, float drop, float rise) +bool collide(physent *d, bool spawn, float drop, float rise) { const float fx1 = d->o.x-d->radius; // figure out integer cube rectangle this entity covers in map const float fy1 = d->o.y-d->radius; @@ -89,7 +87,6 @@ bool collide(dynent *d, bool spawn, float drop, float rise) const int x2 = int(fx2); const int y2 = int(fy2); float hi = 127, lo = -128; - float minfloor = (d->monsterstate && !spawn && d->health>100) ? d->o.z-d->eyeheight-4.5f : -1000.0f; // big monsters are afraid of heights, unless angry :) for(int x = x1; x<=x2; x++) for(int y = y1; y<=y2; y++) // collide with map { @@ -123,7 +120,6 @@ bool collide(dynent *d, bool spawn, float drop, float rise) }; if(ceillo) lo = floor; - if(flooreyeheight+d->aboveeye) return false; @@ -133,23 +129,18 @@ bool collide(dynent *d, bool spawn, float drop, float rise) float headspace = 10; loopv(players) // collide with other players { - dynent *o = players[i]; + playerent *o = players[i]; if(!o || o==d) continue; if(!plcollide(d, o, headspace, hi, lo)) return false; }; loopv(bots) // Added by Rick: collide with other bots { - dynent *o = bots[i]; + botent *o = bots[i]; if(!o || o==d) continue; if(!plcollide(d, o, headspace, hi, lo)) return false; }; - if(d!=player1 && d->mtype!=M_NADE) if(!plcollide(d, player1, headspace, hi, lo)) return false; - //dvector &v = getmonsters(); - // this loop can be a performance bottleneck with many monster on a slow cpu, - // should replace with a blockmap but seems mostly fast enough - // Modified by Rick: Added v[i] pointer check - //loopv(v) if(v[i] && !vreject(d->o, v[i]->o, 7.0f) && d!=v[i] && !plcollide(d, v[i], headspace, hi, lo)) return false; + if(d!=player1/*&& d->mtype!=M_NADE*/) if(!plcollide(d, player1, headspace, hi, lo)) return false; headspace -= 0.01f; mmcollide(d, hi, lo); // collide with map models @@ -168,7 +159,7 @@ bool collide(dynent *d, bool spawn, float drop, float rise) { d->o.z = lo+d->eyeheight; // stick on step } - else if(space>-1.26f && !d->isphysent) d->o.z += rise; // rise thru stair + else if(space>-1.26f && d->type!=ENT_BOUNCE) d->o.z += rise; // rise thru stair else return false; } else @@ -191,7 +182,7 @@ bool collide(dynent *d, bool spawn, float drop, float rise) VAR(maxroll, 0, 3, 20); -void selfdamage(dynent *d, int dm) +void selfdamage(playerent *d, int dm) { if(d==player1) selfdamage(dm, -1, d); else { addmsg(SV_DAMAGE, "ri3", d, dm, d->lifesequence); }; @@ -205,7 +196,7 @@ void selfdamage(dynent *d, int dm) // moveres indicated the physics precision (which is lower for monsters and multiplayer prediction) // local is false for multiplayer prediction -void moveplayer(dynent *pl, int moveres, bool local, int curtime) +void moveplayer(physent *pl, int moveres, bool local, int curtime) { const bool water = hdr.waterlevel>pl->o.z-0.5f; const bool floating = (editmode && local) || pl->state==CS_EDITING; @@ -217,7 +208,7 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) d.x = (float)(move*cosf(RAD*(pl->yaw-90))); d.y = (float)(move*sinf(RAD*(pl->yaw-90))); - d.z = (float) pl->isphysent ? pl->vel.z : 0; + d.z = (float)pl->type==ENT_BOUNCE ? pl->vel.z : 0; if(floating || water) { @@ -240,17 +231,14 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) d = pl->vel; d.mul(speed); // d is now frametime based velocity vector - if(pl->isphysent) + if(pl->type==ENT_BOUNCE) { - float dist = d.magnitude(); - pl->pitch += dist*pl->rotspeed*5.0f; + float dist = d.magnitude(), rotspeed = ((bounceent *)pl)->rotspeed; + pl->pitch += dist*rotspeed*5.0f; if(pl->pitch>360.0f) pl->pitch = 0.0f; - pl->yaw += dist*pl->rotspeed*5.0f; + pl->yaw += dist*rotspeed*5.0f; if(pl->yaw>360.0f) pl->yaw = 0.0f; - } - - pl->blocked = false; - pl->moving = true; + }; if(floating) // just apply velocity { @@ -261,8 +249,11 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) { if(pl->onladder) { - if(pl->k_up) pl->vel.z = 0.75; - else if(pl->k_down) pl->vel.z = -0.75; + if(pl->type==ENT_PLAYER || pl->type==ENT_BOT) + { + if(((playerent *)pl)->k_up) pl->vel.z = 0.75; + else if(((playerent *)pl)->k_down) pl->vel.z = -0.75; + }; pl->timeinair = 0; } else @@ -275,11 +266,10 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) pl->vel.z = 2.0f; //1.7f; // physics impulse upwards if(water) { pl->vel.x /= 8; pl->vel.y /= 8; }; // dampen velocity change even harder, gives correct water feel if(local) playsoundc(S_JUMP); - else if(pl->monsterstate) playsound(S_JUMP, &pl->o); - else if(pl->bIsBot) botplaysound(S_JUMP, pl); // Added by Rick + else if(pl->type==ENT_BOT) botplaysound(S_JUMP, (botent *)pl); // Added by Rick } pl->timeinair = 0; - if(pl->isphysent) pl->vel.z *= 0.7f; + if(pl->type==ENT_BOUNCE) pl->vel.z *= 0.7f; } else { @@ -287,9 +277,9 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) }; }; - const float gravity = pl->isphysent ? pl->gravity : 20; + const float gravity = pl->type==ENT_BOUNCE ? pl->gravity : 20; const float f = 1.0f/moveres; - float dropf = pl->isphysent ? ((gravity-1)+pl->timeinair/14.0f) : ((gravity-1)+pl->timeinair/15.0f); // incorrect, but works fine + float dropf = pl->type==ENT_BOUNCE ? ((gravity-1)+pl->timeinair/14.0f) : ((gravity-1)+pl->timeinair/15.0f); // incorrect, but works fine if(water) { dropf = 5; pl->timeinair = 0; }; // float slowly down in water if(pl->onladder) { dropf = 0; pl->timeinair = 0; }; float drop = dropf*curtime/gravity/100/moveres; // at high fps, gravity kicks in too fast @@ -303,12 +293,11 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) pl->o.z += f*d.z; if(collide(pl, false, drop, rise)) continue; // player stuck, try slide along y axis - pl->blocked = true; pl->o.x -= f*d.x; if(collide(pl, false, drop, rise)) { d.x = 0; - if(pl->isphysent) pl->vel.x = -pl->vel.x; + if(pl->type==ENT_BOUNCE) pl->vel.x = -pl->vel.x; continue; }; pl->o.x += f*d.x; @@ -317,12 +306,11 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) if(collide(pl, false, drop, rise)) { d.y = 0; - if(pl->isphysent) pl->vel.y = -pl->vel.y; + if(pl->type==ENT_BOUNCE) pl->vel.y = -pl->vel.y; continue; }; pl->o.y += f*d.y; // try just dropping down - pl->moving = false; pl->o.x -= f*d.x; pl->o.y -= f*d.y; if(collide(pl, false, drop, rise)) @@ -335,20 +323,6 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) }; }; - // detect wether player is outside map, used for skipping zbuffer clear mostly - - if(pl->o.x < 0 || pl->o.x >= ssize || pl->o.y <0 || pl->o.y > ssize) - { - pl->outsidemap = true; - } - else - { - sqr *s = S((int)pl->o.x, (int)pl->o.y); - pl->outsidemap = SOLID(s) - || pl->o.z < s->floor - (s->type==FHF ? s->vdelta/4 : 0) - || pl->o.z > s->ceil + (s->type==CHF ? s->vdelta/4 : 0); - }; - // automatically apply smooth roll when strafing if(pl->strafe==0) @@ -368,7 +342,7 @@ void moveplayer(dynent *pl, int moveres, bool local, int curtime) else if(pl->inwater && !water) playsound(S_SPLASH1, &pl->o); pl->inwater = water; // Added by Rick: Easy hack to store previous locations of all players/monsters/bots - pl->PrevLocations.Update(pl->o); + if(pl->type==ENT_PLAYER || pl->type==ENT_BOT) ((playerent *)pl)->PrevLocations.Update(pl->o); // End add }; @@ -390,79 +364,41 @@ void physicsframe() // optimally schedule physics frames inside the gra }; }; -void moveplayer(dynent *pl, int moveres, bool local) +void moveplayer(physent *pl, int moveres, bool local) { loopi(physicsrepeat) moveplayer(pl, moveres, local, min(curtime, minframetime)); }; -vector physents; +vector bounceents; -physent *new_physent() +bounceent *newbounceent() { - physent *p = new physent; - - p->yaw = 270; - p->pitch = 0; - p->roll = 0; - p->isphysent = true; - p->rotspeed = 1.0f; - - p->maxspeed = 40; - p->outsidemap = false; - p->inwater = false; - p->radius = 0.2f; - p->eyeheight = 0.3f; - p->aboveeye = 0.0f; - p->frags = 0; - p->plag = 0; - p->ping = 0; - p->lastupdate = lastmillis; - p->enemy = NULL; - p->monsterstate = 0; - p->name[0] = p->team[0] = 0; - p->blocked = false; - p->lifesequence = 0; - p->dynent::state = CS_ALIVE; - p->state = PHYSENT_NONE; - p->shots = 0; - p->reloading = false; - p->nextprimary = 1; - p->hasarmour = false; - - p->k_left = false; - p->k_right = false; - p->k_up = false; - p->k_down = false; - p->jumpnext = false; - p->onladder = false; - p->strafe = 0; - p->move = 0; - - physents.add(p); + bounceent *p = new bounceent; + bounceents.add(p); return p; } -extern void explode_nade(physent *i); +extern void explode_nade(bounceent *i); -void mphysents() +void mbounceents() { - loopv(physents) if(physents[i]) + loopv(bounceents) if(bounceents[i]) { - physent *p = physents[i]; - if(p->state == NADE_THROWED || p->state == GIB) moveplayer(p, 2, false); + bounceent *p = bounceents[i]; + if(p->bouncestate == NADE_THROWED || p->bouncestate == GIB) moveplayer(p, 2, false); if(lastmillis - p->millis >= p->timetolife) { - if(p->state==NADE_ACTIVATED || p->state==NADE_THROWED) explode_nade(physents[i]); + if(p->bouncestate==NADE_ACTIVATED || p->bouncestate==NADE_THROWED) explode_nade(bounceents[i]); delete p; - physents.remove(i); + bounceents.remove(i); i--; }; }; }; -void clearphysents() +void clearbounceents() { - loopv(physents) if(physents[i]) { delete physents[i]; physents.remove(i); }; + loopv(bounceents) if(bounceents[i]) { delete bounceents[i]; bounceents.remove(i); }; } diff --git a/source/src/protos.h b/source/src/protos.h index 06303df4..56cb74b1 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -19,7 +19,6 @@ extern void writecfg(); extern void keypress(int code, bool isdown, int cooked); extern void rendercommand(int x, int y); extern void renderconsole(); -// extern void conoutf(const char *s, int a = 0, int b = 0, int c = 0); Moved to cube.h by Rick extern char *getcurcommand(); extern char *addreleaseaction(char *s); @@ -50,7 +49,7 @@ extern Texture *crosshair; extern void gl_init(int w, int h, int bpp, int depth, int fsaa); extern void cleangl(); extern void gl_drawframe(int w, int h, float changelod, float curfps); -extern Texture *textureload(const char *name, bool clamp = false, bool highqual = false); +extern Texture *textureload(const char *name, bool clamp = false); extern void mipstats(int a, int b, int c); extern void vertf(float v1, float v2, float v3, sqr *ls, float t1, float t2); extern void addstrip(int type, int tex, int start, int n); @@ -94,16 +93,16 @@ extern void updateworld(int curtime, int lastmillis); extern void startmap(char *name); extern void changemap(char *name); extern void initclient(); -extern void spawnplayer(dynent *d, bool secure=false); -extern void selfdamage(int damage, int actor, dynent *act, bool gib=false); -extern dynent *newdynent(); +extern void spawnplayer(playerent *d, bool secure=false); +extern void selfdamage(int damage, int actor, playerent *act, bool gib=false); +extern playerent *newplayerent(); +extern botent *newbotent(); extern char *getclientmap(); extern const char *modestr(int n); -extern void zapdynent(dynent *&d); -extern dynent *getclient(int cn); -extern dynent *getbot(int cn); // Added by Rick +extern void zapplayer(playerent *&d); +extern playerent *getclient(int cn); +extern botent *getbot(int cn); // Added by Rick extern void timeupdate(int timeremain); -extern void resetmovement(dynent *d); extern void fixplayer1range(); extern void respawnself(); // EDIT: AH extern void ctf_death(); @@ -114,8 +113,8 @@ extern void mastercommand(int cmd, int arg1); // clientextras extern void renderclients(); -extern void renderclient(dynent *d, bool team, char *mdlname, float scale); -void showscores(bool on); +extern void renderclient(playerent *d, char *mdlname, char *vwepname); +extern void showscores(bool on); extern void renderscores(); // world @@ -186,9 +185,9 @@ extern void damageblend(int n); extern void addshotline(dynent *d, vec &from, vec &to); extern void rendershotlines(); extern void shotlinereset(); -extern void renderphysents(); +extern void renderbounceents(); extern bool scoped; -extern void addgib(dynent *d); +extern void addgib(playerent *d); extern void loadingscreen(); // renderparticles @@ -212,31 +211,31 @@ extern void demodamage(int damage, vec &o); extern void demoblend(int damage); // physics -extern void moveplayer(dynent *pl, int moveres, bool local); -extern bool collide(dynent *d, bool spawn, float drop, float rise); -extern void entinmap(dynent *d); +extern void moveplayer(physent *pl, int moveres, bool local); +extern bool collide(physent *d, bool spawn, float drop, float rise); +extern void entinmap(physent *d); extern void setentphysics(int mml, int mmr); extern void physicsframe(); -extern void movephysent(physent *pl); -extern physent *new_physent(); -extern void mphysents(); -extern void clearphysents(); +extern bounceent *newbounceent(); +extern void mbounceents(); +extern void clearbounceents(); // sound extern void playsound(int n, vec *loc = 0); extern void playsoundc(int n); extern void initsound(); extern void cleansound(); -extern void botplaysound(int n, dynent *b); // Added by Rick +extern void botplaysound(int n, botent *b); // Added by Rick extern void music(char *name); -// rendermd2 -extern void rendermodel(char *mdl, int frame, int range, int tex, float rad, float x, float y, float z, float yaw, float pitch, bool teammate, float scale, float speed, int snap = 0, int basetime = 0, bool oculling=true, dynent *d=NULL); +// rendermodel +extern void rendermodel(char *mdl, int anim, int tex, float rad, float x, float y, float z, float yaw, float pitch, float speed, int basetime = 0, dynent *d = NULL, char *vwepmdl = NULL, float scale = 1.0f); extern mapmodelinfo &getmminfo(int i); +extern int findanim(const char *name); +extern void loadskin(const char *dir, const char *altdir, Texture *&skin, model *m); -// rendermd3 -extern void rendermd3gun(); -extern void loadweapons(); +// hudgun +extern void renderhudgun(); // server enum { DISC_NONE = 0, DISC_EOP, DISC_CN, DISC_MKICK, DISC_MBAN, DISC_TAGT, DISC_BANREFUSE, DISC_WRONGPW, DISC_MLOGINFAIL, DISC_MAXCLIENTS }; @@ -264,14 +263,14 @@ extern ENetPacket *recvmap(int n); // weapon //extern void selectgun(int a = -1, int b = -1, int c =-1); -extern void shoot(dynent *d, vec &to); -extern void shootv(int gun, vec &from, vec &to, dynent *d = 0, bool local = false, int nademillis=0); +extern void shoot(playerent *d, vec &to); +extern void shootv(int gun, vec &from, vec &to, playerent *d = 0, bool local = false, int nademillis=0); extern void createrays(vec &from, vec &to); extern void moveprojectiles(float time); extern void projreset(); -extern dynent *playerincrosshair(); +extern playerent *playerincrosshair(); extern int reloadtime(int gun); -extern void reload(dynent *d); +extern void reload(playerent *d); extern int attackdelay(int gun); extern int magsize(int gun); extern int kick_rot(int gun); @@ -282,21 +281,21 @@ extern void checkweaponswitch(); extern void weaponswitch(int gun); extern void setscope(bool activate); // Added by Rick -extern dynent *botincrosshair(); +extern botent *botincrosshair(); extern bool intersect(dynent *d, vec &from, vec &to, vec *end = NULL); // End add by Rick // entities extern void renderents(); extern void putitems(ucharbuf &p); -extern void realpickup(int n, dynent *d); +extern void realpickup(int n, playerent *d); extern void flagaction(int team, int action); extern void renderentities(); extern void resetspawns(); extern void setspawn(int i, bool on); extern void baseammo(int gun); extern void checkitems(); -extern void radd(dynent *d); +extern void radd(playerent *d); // Added by Rick extern void botbaseammo(int gun, dynent *d); extern bool intersect(entity *e, vec &from, vec &to, vec *end=NULL); diff --git a/source/src/renderextras.cpp b/source/src/renderextras.cpp index 0984cda3..15c98450 100644 --- a/source/src/renderextras.cpp +++ b/source/src/renderextras.cpp @@ -208,7 +208,7 @@ void renderents() // show sparkly thingies for map entities in edit mode { entity &e = ents[i]; if(e.type==NOTUSED) continue; - vec v = { e.x, e.y, e.z }; + vec v(e.x, e.y, e.z); particle_splash(2, 2, 40, v); }; int e = closestent(); @@ -252,8 +252,8 @@ void readdepth(int w, int h) worldpos.x = (float)worldx; worldpos.y = (float)worldy; worldpos.z = (float)worldz; - vec r = { (float)mm[0], (float)mm[4], (float)mm[8] }; - vec u = { (float)mm[1], (float)mm[5], (float)mm[9] }; + vec r((float)mm[0], (float)mm[4], (float)mm[8]); + vec u((float)mm[1], (float)mm[5], (float)mm[9]); setorient(r, u); }; @@ -352,8 +352,8 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat glEnable(GL_TEXTURE_2D); - dynent *player = playerincrosshair(); - dynent *bot = botincrosshair(); + playerent *player = playerincrosshair(); + playerent *bot = botincrosshair(); if(getcurcommand()) rendercommand(20, 1570); else if(closeent[0]) draw_text(closeent, 20, 1570); else if(player || (bot && (player=bot))) draw_text(player->name, 20, 1570); @@ -592,16 +592,16 @@ void rendershotlines() }; }; -void renderphysents() +void renderbounceents() { - loopv(physents) + loopv(bounceents) { - physent *p = physents[i]; + bounceent *p = bounceents[i]; if(!p) continue; string model; float z = p->o.z; - switch(p->state) + switch(p->bouncestate) { case NADE_THROWED: s_strcpy(model, "weapons/grenade/static"); @@ -621,7 +621,8 @@ void renderphysents() }; }; path(model); - rendermodel(model, 0, 1, 0, 0, p->o.x, z, p->o.y, p->yaw, p->pitch, false, 2.0f, 100.0f, 0, 0); + // scale: 2.0f + rendermodel(model, ANIM_MAPMODEL|ANIM_LOOP, 0, 0, p->o.x, z, p->o.y, p->yaw, p->pitch, 10.0f); }; }; @@ -629,24 +630,21 @@ VAR(gibnum, 0, 6, 1000); VAR(gibttl, 0, 5000, 15000); VAR(gibspeed, 1, 5, 20); -void addgib(dynent *d) +void addgib(playerent *d) { if(!d) return; playsound(S_GIB, &d->o); loopi(gibnum) { - physent *p = new_physent(); + bounceent *p = newbounceent(); p->owner = d; p->millis = lastmillis; p->timetolife = gibttl+rnd(10)*100; p->state = GIB; - p->isphysent = true; p->gravity = 20; - p->timeinair = 0; - p->onfloor = false; p->o = d->o; p->o.z -= d->aboveeye; @@ -667,7 +665,7 @@ void addgib(dynent *d) void loadingscreen() { static Texture *logo = NULL; - if(!logo) logo = textureload("packages/misc/full_logo.png", false, true); + if(!logo) logo = textureload("packages/misc/full_logo.png", false); glPushMatrix(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp index 3d7d8811..86ca5d93 100644 --- a/source/src/rendergl.cpp +++ b/source/src/rendergl.cpp @@ -12,7 +12,7 @@ bool hasoverbright = false; -int glmaxtexsize = 256; +VAR(maxtexsize, 0, 0, 4096); void gl_init(int w, int h, int bpp, int depth, int fsaa) { @@ -44,7 +44,7 @@ void gl_init(int w, int h, int bpp, int depth, int fsaa) if(strstr(exts, "GL_EXT_texture_env_combine")) hasoverbright = true; else conoutf("WARNING: cannot use overbright lighting, using old lighting model!"); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glmaxtexsize); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize); GLUquadricObj *qsphere = gluNewQuadric(); if(!qsphere) fatal("glu sphere"); @@ -66,7 +66,7 @@ void cleangl() { }; -GLuint installtex(const char *texname, int &xs, int &ys, bool clamp, bool highqual) +GLuint installtex(const char *texname, int &xs, int &ys, bool clamp) { SDL_Surface *s = IMG_Load(texname); if(!s) { conoutf("couldn't load texture %s", texname); return 0; }; @@ -79,11 +79,11 @@ GLuint installtex(const char *texname, int &xs, int &ys, bool clamp, bool highqu glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP_TO_EDGE : GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, highqual ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); //NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); xs = s->w; ys = s->h; - while(xs>glmaxtexsize || ys>glmaxtexsize) { xs /= 2; ys /= 2; }; + if(maxtexsize) while(xs>maxtexsize || ys>maxtexsize) { xs /= 2; ys /= 2; }; int mode = s->format->BitsPerPixel==24 ? GL_RGB : GL_RGBA; uchar *scaledimg = (uchar *)s->pixels; if(xs!=s->w) @@ -106,7 +106,7 @@ GLuint installtex(const char *texname, int &xs, int &ys, bool clamp, bool highqu // each texture slot can have multople texture frames, of which currently only the first is used // additional frames can be used for various shaders -Texture *textureload(const char *name, bool clamp, bool highqual) +Texture *textureload(const char *name, bool clamp) { string pname; s_strcpy(pname, name); @@ -114,7 +114,7 @@ Texture *textureload(const char *name, bool clamp, bool highqual) Texture *t = textures.access(pname); if(t) return t; int xs, ys; - GLuint id = installtex(pname, xs, ys, clamp, highqual); + GLuint id = installtex(pname, xs, ys, clamp); if(!id) return crosshair; char *key = newstring(pname); t = &textures[key]; @@ -301,25 +301,18 @@ VAR(hudgun,0,1,1); char *hudgunnames[] = { "knife", "pistol", "shotgun", "subgun", "sniper", "assault", "grenade"}; -void drawhudmodel(int start, int end, float speed, int base) -{ - s_sprintfd(mdl)("hudguns/%s", hudgunnames[player1->gunselect]); - rendermodel(mdl, start, end, 0, 1.0f, player1->o.x, player1->o.z, player1->o.y, player1->yaw+90, player1->pitch, false, 1.0f, speed, 0, base); -}; - - void drawhudgun(int w, int h, float aspect, int farplane) { if(scoped && player1->gunselect==GUN_SNIPER) return; glEnable(GL_CULL_FACE); - + glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective((float)100.0f*h/w, aspect, 0.3f, farplane); // fov fixed at 100° glMatrixMode(GL_MODELVIEW); - - if(hudgun && player1->state!=CS_DEAD)rendermd3gun(); + + if(hudgun && player1->state!=CS_DEAD) renderhudgun(); rendermenumdl(); glMatrixMode(GL_PROJECTION); @@ -330,6 +323,15 @@ void drawhudgun(int w, int h, float aspect, int farplane) glDisable(GL_CULL_FACE); }; +bool outsidemap(dynent *pl) +{ + if(pl->o.x < 0 || pl->o.x >= ssize || pl->o.y <0 || pl->o.y > ssize) return true; + sqr *s = S((int)pl->o.x, (int)pl->o.y); + return SOLID(s) + || pl->o.z < s->floor - (s->type==FHF ? s->vdelta/4 : 0) + || pl->o.z > s->ceil + (s->type==CHF ? s->vdelta/4 : 0); +}; + void gl_drawframe(int w, int h, float changelod, float curfps) { float hf = hdr.waterlevel-0.3f; @@ -351,7 +353,7 @@ void gl_drawframe(int w, int h, float changelod, float curfps) glFogi(GL_FOG_END, (fog+96)/8); }; - glClear((player1->outsidemap ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT); + glClear((outsidemap(player1) ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -401,7 +403,7 @@ void gl_drawframe(int w, int h, float changelod, float curfps) renderspheres(curtime); renderents(); - renderphysents(); + renderbounceents(); rendershotlines(); diff --git a/source/src/rendermd2.cpp b/source/src/rendermd2.cpp deleted file mode 100644 index 17f725cf..00000000 --- a/source/src/rendermd2.cpp +++ /dev/null @@ -1,359 +0,0 @@ -// rendermd2.cpp: loader code adapted from a nehe tutorial - -#include "cube.h" - -VARP(animationinterpolationtime, 0, 150, 1000); - -struct md2_anpos -{ - int fr1, fr2; - float frac1, frac2; - - void setframes(md2state &a) - { - int time = lastmillis-a.basetime; - fr1 = (int)(time/a.speed); - frac1 = (time-fr1*a.speed)/a.speed; - frac2 = 1-frac1; - //if(a.anim&ANIM_LOOP) // FIXME - { - fr1 = fr1%a.range+a.frame; - fr2 = fr1+1; - if(fr2>=a.frame+a.range) fr2 = a.frame; - } -/* else - { - fr1 = min(fr1, a.range-1)+a.frame; - fr2 = min(fr1+1, a.frame+a.range-1); - }; - if(a.anim&ANIM_REVERSE) - { - fr1 = (a.frame+a.range-1)-(fr1-a.frame); - fr2 = (a.frame+a.range-1)-(fr2-a.frame); - };*/ - }; -}; - -struct md2_header -{ - int magic; - int version; - int skinWidth, skinHeight; - int frameSize; - int numSkins, numVertices, numTexcoords; - int numTriangles, numGlCommands, numFrames; - int offsetSkins, offsetTexcoords, offsetTriangles; - int offsetFrames, offsetGlCommands, offsetEnd; -}; - -struct md2_vertex -{ - uchar vertex[3], lightNormalIndex; -}; - -struct md2_frame -{ - float scale[3]; - float translate[3]; - char name[16]; - md2_vertex vertices[1]; -}; - -struct md2 -{ - int numGlCommands; - int* glCommands; - int numTriangles; - int frameSize; - int numFrames; - int numVerts; - char* frames; - vec **mverts; - int displaylist; - int displaylistverts; - - mapmodelinfo mmi; - char *loadname; - Texture *skin; - bool loaded; - - bool load(char* filename); - void render(vec &light, int numFrame, int range, float x, float y, float z, float yaw, float pitch, float scale, float speed, int snap, int basetime, dynent *d=NULL); - void scale(int frame, float scale, int sn); - - md2() : numGlCommands(0), frameSize(0), numFrames(0), displaylist(0), skin(NULL), loaded(false) {}; - - ~md2() - { - if(glCommands) - delete [] glCommands; - if(frames) - delete [] frames; - }; -}; - - -bool md2::load(char* filename) -{ - FILE* file; - md2_header header; - - if((file= fopen(filename, "rb"))==NULL) return false; - - fread(&header, sizeof(md2_header), 1, file); - endianswap(&header, sizeof(int), sizeof(md2_header)/sizeof(int)); - - if(header.magic!= 844121161 || header.version!=8) return false; - - frames = new char[header.frameSize*header.numFrames]; - if(frames==NULL) return false; - - fseek(file, header.offsetFrames, SEEK_SET); - fread(frames, header.frameSize*header.numFrames, 1, file); - - for(int i = 0; i < header.numFrames; ++i) - { - endianswap(frames + i * header.frameSize, sizeof(float), 6); - } - - glCommands = new int[header.numGlCommands]; - if(glCommands==NULL) return false; - - fseek(file, header.offsetGlCommands, SEEK_SET); - fread(glCommands, header.numGlCommands*sizeof(int), 1, file); - - endianswap(glCommands, sizeof(int), header.numGlCommands); - - numFrames = header.numFrames; - numGlCommands= header.numGlCommands; - frameSize = header.frameSize; - numTriangles = header.numTriangles; - numVerts = header.numVertices; - - fclose(file); - - mverts = new vec*[numFrames]; - loopj(numFrames) mverts[j] = NULL; - - return true; -}; - -float snap(int sn, float f) { return sn ? (float)(((int)(f+sn*0.5f))&(~(sn-1))) : f; }; - -void md2::scale(int frame, float scale, int sn) -{ - mverts[frame] = new vec[numVerts]; - md2_frame *cf = (md2_frame *) ((char*)frames+frameSize*frame); - float sc = 16.0f/scale; - loop(vi, numVerts) - { - uchar *cv = (uchar *)&cf->vertices[vi].vertex; - vec *v = &(mverts[frame])[vi]; - v->x = (snap(sn, cv[0]*cf->scale[0])+cf->translate[0])/sc; - v->y = -(snap(sn, cv[1]*cf->scale[1])+cf->translate[1])/sc; - v->z = (snap(sn, cv[2]*cf->scale[2])+cf->translate[2])/sc; - }; -}; - -void md2::render(vec &light, int frame, int range, float x, float y, float z, float yaw, float pitch, float sc, float speed, int snap, int basetime, dynent *d) -{ - if(range==0 || frame+range-1>numFrames) - { - printf("warning: model %s, invalid frame (%i) or range (%i)", loadname, frame, range); - return; - } - - md2state ai; - ai.frame = frame; - ai.basetime = basetime; - ai.range = range; - ai.speed = speed; - - loopi(ai.range) if(!mverts[ai.frame+i]) scale(ai.frame+i, sc, snap); - - if(d) - { - if(d->lastanimswitchtime==-1) { d->current = ai; d->lastanimswitchtime = lastmillis-animationinterpolationtime*2; } - else if(d->current != ai) - { - if(lastmillis-d->lastanimswitchtime>animationinterpolationtime/2) d->prev = d->current; - d->current = ai; - d->lastanimswitchtime = lastmillis; - }; - }; - - glPushMatrix (); - glTranslatef(x, y, z); - glRotatef(yaw+180, 0, -1, 0); - glRotatef(pitch, 0, 0, 1); - - glColor3fv((float *)&light); - - if(displaylist && ai.frame==0 && ai.range==1) - { - glCallList(displaylist); - xtraverts += displaylistverts; - } - else - { - if(ai.frame==0 && ai.range==1) - { - static int displaylistn = 10; - glNewList(displaylist = displaylistn++, GL_COMPILE); - displaylistverts = xtraverts; - }; - - md2_anpos prev, current; - current.setframes(d ? d->current : ai); -#ifdef _DEBUG - prev.setframes(ai); -#endif - vec *verts1 = mverts[current.fr1], *verts2 = mverts[current.fr2], *verts1p, *verts2p; - float aifrac1, aifrac2; - bool doai = d && lastmillis-d->lastanimswitchtimeprev); - verts1p = mverts[prev.fr1]; - verts2p = mverts[prev.fr2]; - aifrac1 = (lastmillis-d->lastanimswitchtime)/(float)animationinterpolationtime; - aifrac2 = 1-aifrac1; - if(!verts1p || !verts2p) return; //fixme - }; - - for(int *command = glCommands; (*command)!=0;) - { - int numVertex = *command++; - if(numVertex>0) { glBegin(GL_TRIANGLE_STRIP); } - else { glBegin(GL_TRIANGLE_FAN); numVertex = -numVertex; }; - - loopi(numVertex) - { - float tu = *((float*)command++); - float tv = *((float*)command++); - glTexCoord2f(tu, tv); - int vn = *command++; - vec &v1 = verts1[vn]; - vec &v2 = verts2[vn]; - #define ip(v1, v2, c) (v1.c*current.frac2+v2.c*current.frac1) - #define ipv(v1, v2, c) (v1 ## p.c*prev.frac2+v2 ## p.c*prev.frac1) - #define ipa(v1, v2, c) (ip(v1, v2, c)*aifrac1+ipv(v1, v2, c)*aifrac2) - if(doai) - { - vec &v1p = verts1p[vn], &v2p = verts2p[vn]; - glVertex3f(ipa(v1, v2, x), ipa(v1, v2, z), ipa(v1, v2, y)); - } - else glVertex3f(ip(v1, v2, x), ip(v1, v2, z), ip(v1, v2, y)); - }; - - xtraverts += numVertex; - - glEnd(); - }; - - if(displaylist) - { - glEndList(); - displaylistverts = xtraverts-displaylistverts; - }; - }; - - glPopMatrix(); -} - -hashtable mdllookup; -vector mapmodels; - -void delayedload(md2 *m) -{ - if(!m->loaded) - { - s_sprintfd(name1)("packages/models/%s/tris.md2", m->loadname); - if(!m->load(path(name1))) fatal("loadmodel: ", name1); - s_sprintfd(name2)("packages/models/%s/skin.jpg", m->loadname); - m->skin = textureload(name2); - m->loaded = true; - }; -}; - -md2 *loadmodel(char *name) -{ - - md2 **mm = mdllookup.access(name); - if(mm) return *mm; - md2 *m = new md2(); - mapmodelinfo mmi = { 2, 2, 0, 0, "" }; - m->mmi = mmi; - m->loadname = newstring(name); - mdllookup.access(m->loadname, &m); - return m; -}; - -void mapmodel(char *rad, char *h, char *zoff, char *snap, char *name) -{ - s_sprintfd(lname)("mapmodels/%s", name); - md2 *m = loadmodel(lname); - mapmodelinfo mmi = { atoi(rad), atoi(h), atoi(zoff), atoi(snap), m->loadname }; - m->mmi = mmi; - mapmodels.add(m); -}; - -void mapmodelreset() { mapmodels.setsize(0); }; - -mapmodelinfo &getmminfo(int i) { return mapmodels.inrange(i) ? mapmodels[i]->mmi : *(mapmodelinfo *)0; }; - -COMMAND(mapmodel, ARG_5STR); -COMMAND(mapmodelreset, ARG_NONE); - -void rendermodel(char *mdl, int frame, int range, int tex, float rad, float x, float y, float z, float yaw, float pitch, bool teammate, float scale, float speed, int snap, int basetime, bool oculling, dynent *d) -{ - md2 *m = loadmodel(mdl); - - if(oculling && isoccluded(player1->o.x, player1->o.y, x-rad, z-rad, rad*2)) return; - - delayedload(m); - - int xs, ys; - glBindTexture(GL_TEXTURE_2D, tex ? lookuptexture(tex, xs, ys) : m->skin->id); - - int ix = (int)x; - int iy = (int)z; - vec light = { 1.0f, 1.0f, 1.0f }; - - if(!OUTBORD(ix, iy)) - { - sqr *s = S(ix,iy); - float ll = 256.0f; // 0.96f; - float of = 0.0f; // 0.1f; - light.x = s->r/ll+of; - light.y = s->g/ll+of; - light.z = s->b/ll+of; - }; - -/* - if(teammate) - { - light.x *= 0.6f; - light.y *= 0.7f; - light.z *= 1.2f; - }; -*/ - - m->render(light, frame, range, x, y, z, yaw, pitch, scale, speed, snap, basetime, d); -}; - - -void preload_mapmodels() -{ - int xs, ys; - loopv(ents) - { - entity &e = ents[i]; - if(e.type!=MAPMODEL || !mapmodels.inrange(e.attr2)) continue; - md2 *m = mapmodels[e.attr2]; - if(!m) continue; - delayedload(m); - if(e.attr4) lookuptexture(e.attr4, xs, ys); - }; -}; - diff --git a/source/src/rendermd3.cpp b/source/src/rendermd3.cpp deleted file mode 100644 index 4c000fb2..00000000 --- a/source/src/rendermd3.cpp +++ /dev/null @@ -1,530 +0,0 @@ -// code for loading, linking and rendering md3 models -// See http://www.icculus.org/homepages/phaethon/q3a/formats/md3format.html for informations about the md3 format - -#include "cube.h" - -enum { MDL_LOWER = 0, MDL_UPPER, MDL_HEAD }; - -enum { MDL_GUN_IDLE = 0, MDL_GUN_ATTACK, MDL_GUN_RELOAD, MDL_GUN_ATTACK2}; // attack2 is for grenade only - -#define MD3_DEFAULT_SCALE 0.08f - -struct vec2 -{ - float x, y; -}; - -struct md3tag -{ - char name[64]; - float pos[3]; - float rotation[3][3]; -}; - -struct md3vertex -{ - signed short vertex[3]; - uchar normal[2]; -}; - -struct md3triangle -{ - int vertexindices[3]; -}; - -struct md3animinfo -{ - int start; - int num; - bool loop; - int fps; -}; - -struct md3header -{ - char id[4]; - int version; - char name[64]; - int flags; - int numframes, numtags, nummeshes, numskins; - int ofs_frames, ofs_tags, ofs_meshes, ofs_eof; // offsets -}; - -struct md3meshheader -{ - char id[4]; - char name[64]; - int flags; - int numframes, numshaders, numvertices, numtriangles; - int ofs_triangles, ofs_shaders, ofs_uv, ofs_vertices, meshsize; // offsets -}; - -struct md3mesh -{ - char name[64]; - md3triangle *triangles; - vec *vertices; - vec2 *uv; - int numtriangles, numvertices; // numvertices == numUV - Texture *skin; -}; - -struct md3model -{ - vector meshes; - vector animations; - md3state *animstate; - md3model **links; - md3tag *tags; - int numframes, numtags; - bool loaded; - vec scale; - bool mirrored; - void setanim(int anim); - void setanimstate(md3state &as); - bool link(md3model *link, char *tag); - bool load(char *path, bool _mirrored); - void render(); - void draw(float x, float y, float z, float yaw, float pitch, float rad, vec &light); - md3model(); - ~md3model(); -}; - -md3model::md3model() -{ - mirrored = false; - loaded = false; - scale.x = scale.y = scale.z = MD3_DEFAULT_SCALE; -// animstate = NULL; - animstate = new md3state(); - animstate->lastTime = lastmillis; -}; - -md3model::~md3model() -{ - loopv(meshes){ - if(meshes[i].vertices) delete [] meshes[i].vertices; - if(meshes[i].triangles) delete [] meshes[i].triangles; - if(meshes[i].uv) delete [] meshes[i].uv; - }; - if(links) delete[] links; - if(tags) delete [] tags; -}; - -void md3model::setanimstate(md3state &as) -{ - animstate->anim = as.anim; - animstate->frm = as.frm; - animstate->lastTime = as.lastTime; -}; - -void md3model::setanim(int anim) -{ - if(animstate->anim != anim) animstate->lastTime = lastmillis; - animstate->anim = anim; -}; - -bool md3model::link(md3model *link, char *tag) -{ - loopi(numtags) - if(strcmp(tags[i].name, tag) == 0) - { - links[i] = link; - return true; - }; - return false; -}; - -bool md3model::load(char *path, bool _mirrored=false) -{ - mirrored = _mirrored; - if(!path) return false; - FILE *f = fopen(path, "rb"); - if(!f) return false; - md3header header; - fread(&header, sizeof(md3header), 1, f); - - endianswap(&header.version, sizeof(int), 1); - endianswap(&header.flags, sizeof(int), 9); - if(strncmp(header.id, "IDP3", 4) != 0 || header.version != 15) // header check - - if(header.id[0] != 'I' || header.id[1] != 'D' || header.id[2] != 'P' || header.id[3] != '3' || header.version != 15) // header check - { printf("corruped header in md3 model: %s", path); return false; }; - - tags = new md3tag[header.numframes * header.numtags]; - fseek(f, header.ofs_tags, SEEK_SET); - fread(tags, sizeof(md3tag), header.numframes * header.numtags, f); - loopi(header.numframes*header.numtags) endianswap(&tags[i].pos, sizeof(float), 12); - numframes = header.numframes; - numtags = header.numtags; - - links = new md3model *[header.numtags]; - loopi(header.numtags) links[i] = NULL; - - int mesh_offset = ftell(f); - - loopi(header.nummeshes) - { - md3mesh mesh; - md3meshheader mheader; - fseek(f, mesh_offset, SEEK_SET); - fread(&mheader, sizeof(md3meshheader), 1, f); - endianswap(&mheader.flags, sizeof(int), 10); - s_strncpy(mesh.name, mheader.name, 64); - - mesh.triangles = new md3triangle[mheader.numtriangles]; - fseek(f, mesh_offset + mheader.ofs_triangles, SEEK_SET); - fread(mesh.triangles, sizeof(md3triangle), mheader.numtriangles, f); // read the triangles - endianswap(mesh.triangles, sizeof(int), 3*mheader.numtriangles); - mesh.numtriangles = mheader.numtriangles; - - mesh.uv = new vec2[mheader.numvertices]; - fseek(f, mesh_offset + mheader.ofs_uv , SEEK_SET); - fread(mesh.uv, sizeof(vec2), mheader.numvertices, f); // read the UV data - endianswap(mesh.uv, sizeof(float), 2*mheader.numvertices); - - md3vertex *vertices = new md3vertex[mheader.numframes * mheader.numvertices]; - fseek(f, mesh_offset + mheader.ofs_vertices, SEEK_SET); - fread(vertices, sizeof(md3vertex), mheader.numframes * mheader.numvertices, f); // read the vertices - endianswap(vertices, sizeof(short), 4*mheader.numframes*mheader.numvertices); - - mesh.vertices = new vec[mheader.numframes * mheader.numvertices]; // transform to our own structure - loopj(mheader.numframes * mheader.numvertices) - { - mesh.vertices[j].x = vertices[j].vertex[0] / 64.0f * (mirrored ? -1 : 1); - mesh.vertices[j].y = vertices[j].vertex[1] / 64.0f; - mesh.vertices[j].z = vertices[j].vertex[2] / 64.0f; - }; - mesh.numvertices = mheader.numvertices; - - meshes.add(mesh); - mesh_offset += mheader.meshsize; - delete [] vertices; - }; - - loaded = true; - return true; -}; - - -void md3model::render() -{ - if(!loaded || meshes.length() <= 0) return; - int nextfrm; - float t = 0.0f; - md3state *a = animstate; - - if(a && animations.length() > a->anim) - { - md3animinfo *info = &animations[a->anim]; - - int time = lastmillis - a->lastTime; - float speed = 1000.0f / (float)info->fps; - a->frm = (int) (time / speed); - - if(!info->loop && a->frm >= info->num-1) - { - a->frm = info->start + info->num-1; - nextfrm = a->frm; - } - else - { - t = (time-a->frm*speed)/speed; - a->frm = info->start+(a->frm % info->num); - nextfrm = a->frm + 1; - if(nextfrm>=info->start+info->num) nextfrm=a->frm; - }; - } - else - { - if(!a) a = new md3state(); - a->frm = 0; - nextfrm = a->frm + 1; - } - - #define interpolate(p1,p2) ((p1) + t * ((p2) - (p1))) - - loopv(meshes) - { - md3mesh *mesh = &meshes[i]; - - glBindTexture(GL_TEXTURE_2D, mesh->skin->id); - - glBegin(GL_TRIANGLES); - loopj(mesh->numtriangles) // triangles - { - loopk(3) // vertices - { - int index = mesh->triangles[j].vertexindices[k]; - vec *point1 = &mesh->vertices[index + a->frm * mesh->numvertices]; - vec *point2 = &mesh->vertices[index + nextfrm * mesh->numvertices]; - - if(mesh->uv) - glTexCoord2f(mesh->uv[index].x, mesh->uv[index].y); - - glVertex3f( interpolate(point1->x, point2->x), - interpolate(point1->y, point2->y), - interpolate(point1->z, point2->z)); - }; - }; - glEnd(); - }; - - loopi(numtags) // render the linked models - interpolate rotation and position of the 'link-tags' - { - md3model *link = links[i]; - if(!link) continue; - GLfloat matrix[16] = {0}; // fixme: un-obfuscate it! - loopj(3) matrix[j] = interpolate(tags[a->frm * numtags + i].rotation[0][j], tags[nextfrm * numtags + i].rotation[0][j]); // rotation - loopj(3) matrix[4 + j] = interpolate(tags[a->frm * numtags + i].rotation[1][j], tags[nextfrm * numtags + i].rotation[1][j]); - loopj(3) matrix[8 + j] = interpolate(tags[a->frm * numtags + i].rotation[2][j], tags[nextfrm * numtags + i].rotation[2][j]); - loopj(3) matrix[12 + j] = interpolate(tags[a->frm * numtags + i].pos[j] , tags[nextfrm * numtags + i].pos[j]); // position - matrix[15] = 1.0f; - glPushMatrix(); - glMultMatrixf(matrix); - link->render(); - glPopMatrix(); - }; -}; - -void md3model::draw(float x, float y, float z, float yaw, float pitch, float rad, vec &light) -{ - glPushMatrix(); - glColor3fv((float *)&light); - glTranslatef(x, y, z); - - glRotatef(yaw+180, 0, -1, 0); - glRotatef(pitch, 0, 0, 1); - glRotatef(-90, 0, 1, 0); - glRotatef(-90, 1, 0, 0); - - glScalef(scale.x, scale.y, scale.z); - - if(mirrored) glCullFace(GL_BACK); - render(); - if(mirrored) glCullFace(GL_FRONT); - - glPopMatrix(); -}; - -void md3setanim(dynent *d, int anim) -{ - if(anim <= BOTH_DEAD3) // assign to both, legs and torso - { - d->animstate[MDL_LOWER].anim = anim; - d->animstate[MDL_UPPER].anim = anim; - } - else if(anim <= TORSO_STAND2) - d->animstate[MDL_UPPER].anim = anim; - else - d->animstate[MDL_LOWER].anim = anim - 7; -}; - -vector models; -vector tmp_animations; -int firstweapon = -1; -string basedir; // necessary for relative path's - -void md3skin(char *objname, char *skin) // called by the {lower|upper|head}.cfg (originally .skin in Q3A) -{ - md3model *mdl = models.last(); - loopv(mdl->meshes) - { - md3mesh *mesh = &mdl->meshes[i]; - if(strcmp(mesh->name, objname) == 0) - { - s_sprintfd(path)("%s/%s", basedir, skin); // 'skin' is a relative url - bool highqual = strstr(basedir, "weapons") != NULL; - mesh->skin = textureload(path, true, highqual); - }; - }; -}; - -COMMAND(md3skin, ARG_2STR); - -void md3animation(char *first, char *nums, char *loopings, char *fps) /* configurable animations */ -{ - md3animinfo &a = tmp_animations.add(); - a.start = atoi(first); - int n = atoi(nums); - if(n<=0) n = 1; - a.num = n; - (atoi(loopings) > 0) ? a.loop = true : a.loop = false; - a.fps = atoi(fps); -}; - -COMMAND(md3animation, ARG_5STR); - -bool loadweapon(char *name, bool isakimbo=false) -{ - if(!name) return false; - sprintf(basedir, "packages/models/weapons/%s", name); - - md3model *mdl = new md3model(); - s_sprintfd(mdl_path)("%s/tris_high.md3", basedir); - s_sprintfd(cfg_path)("%s/default.skin", basedir); - s_sprintfd(modelcfg_path) ("%s/animations.cfg", basedir); - - if(!mdl->load(mdl_path, isakimbo)) - { - printf("could not load: %s\n", mdl_path); - delete mdl; - return false; - } - - models.add(mdl); - exec(cfg_path); - tmp_animations.setsize(0); - exec(modelcfg_path); // load animations - loopj(tmp_animations.length()) mdl->animations.add(tmp_animations[j]); - return true; -} - -void loadweapons() -{ - firstweapon = models.length(); - loopi(NUMGUNS) loadweapon(hudgunnames[i]); - loadweapon(hudgunnames[GUN_PISTOL], true); // akimbo -}; - -VAR(swayspeeddiv, 1, 125, 1000); -VAR(swaymovediv, 1, 200, 1000); - -VAR(swayupspeeddiv, 1, 125, 1000); -VAR(swayupmovediv, 1, 200, 1000); - -VAR(x, 0, 0, 1000); -VAR(y, 0, 0, 1000); -VAR(z, 0, 0, 1000); - -struct weaponmove -{ - float k_rot, kick; - vec pos; - int anim; - - weaponmove() : k_rot(0), kick(0), anim(0) { pos.x = pos.y = pos.z = 0.0f; }; - - void calcmove(vec base, int basetime) - { - int timediff = NADE_THROWING ? (lastmillis-player1->thrownademillis) : lastmillis-basetime; - int animtime = attackdelay(player1->gunselect); - int rtime = reloadtime(player1->gunselect); - - kick = k_rot = 0.0f; - pos = player1->o; - anim = MDL_GUN_IDLE; - - if(player1->weaponchanging) - { - anim = MDL_GUN_RELOAD; - float percent_done = (float)(timediff)*100.0f/(float) WEAPONCHANGE_TIME; - if(percent_done>=100 || percent_done<0) percent_done = 100; - k_rot = -(sin((float)(percent_done*2/100.0f*90.0f)*PI/180.0f)*90); - } - else if(player1->reloading) - { - anim = MDL_GUN_RELOAD; - float percent_done = (float)(timediff)*100.0f/(float)rtime; - if(percent_done>=100 || percent_done<0) percent_done = 100; - k_rot = -(sin((float)(percent_done*2/100.0f*90.0f)*PI/180.0f)*90); - } - else - { - vec sway = base; - float percent_done = 0.0f; - float k_back = 0.0f; - - if(player1->gunselect==player1->lastattackgun) - { - percent_done = timediff*100.0f/(float)animtime; - if(percent_done > 100.0f) percent_done = 100.0f; - // f(x) = -sin(x-1.5)^3 - kick = -sin(pow((1.5f/100.0f*percent_done)-1.5f,3)); - }; - - if(player1->lastaction && player1->lastattackgun==player1->gunselect) - { - if(NADE_THROWING && timedifflastactiongunselect!=GUN_GRENADE && player1->gunselect!=GUN_KNIFE) - { - k_rot = kick_rot(player1->gunselect)*kick; - k_back = kick_back(player1->gunselect)*kick/10; - }; - - float swayspeed = (float) (sin((float)lastmillis/swayspeeddiv))/(swaymovediv/10.0f); - float swayupspeed = (float) (sin((float)lastmillis/swayupspeeddiv-90))/(swayupmovediv/10.0f); - - #define g0(x) ((x) < 0.0f ? -(x) : (x)) - float plspeed = min(1.0f, sqrt(g0(player1->vel.x*player1->vel.x) + g0(player1->vel.y*player1->vel.y))); - - swayspeed *= plspeed/2; - swayupspeed *= plspeed/2; - - float tmp = sway.x; - sway.x = sway.y; - sway.y = -tmp; - - if(swayupspeed<0.0f)swayupspeed = -swayupspeed; // sway a semicirle only - sway.z = 1.0f; - - sway.x *= swayspeed; - sway.y *= swayspeed; - sway.z *= swayupspeed; - - pos.x = player1->o.x-base.x*k_back+sway.x; - pos.y = player1->o.y-base.y*k_back+sway.y; - pos.z = player1->o.z-base.z*k_back+sway.z; - }; - }; -}; - - -void rendergun(md3model *weapon, int lastaction) -{ - int ix = (int)player1->o.x; - int iy = (int)player1->o.y; - vec light = { 1.0f, 1.0f, 1.0f }; - - if(!OUTBORD(ix, iy)) - { - sqr *s = S(ix,iy); - float ll = 256.0f; // 0.96f; - float of = 0.0f; // 0.1f; - light.x = s->r/ll+of; - light.y = s->g/ll+of; - light.z = s->b/ll+of; - }; - - vec unitv; - float dist = worldpos.dist(player1->o, unitv); - unitv.div(dist); - - weaponmove wm; - if(!intermission) wm.calcmove(unitv, lastaction); - weapon->setanim(wm.anim); - weapon->draw(wm.pos.x, wm.pos.z, wm.pos.y, player1->yaw + 90, player1->pitch+wm.k_rot, 1.0f, light); -}; - -void rendermd3gun() -{ - if(firstweapon >= 0) - { - if(player1->akimbo && player1->gunselect==GUN_PISTOL) // akimbo - { - rendergun(models[firstweapon+GUN_PISTOL], player1->akimbolastaction[0]); - rendergun(models[firstweapon+NUMGUNS], player1->akimbolastaction[1]); - } - else - { - md3model *weapon = models[firstweapon + player1->gunselect]; - rendergun(weapon, player1->lastaction); - }; - }; -}; - - diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp new file mode 100644 index 00000000..0c5e9a40 --- /dev/null +++ b/source/src/rendermodel.cpp @@ -0,0 +1,161 @@ +#include "cube.h" + +VARP(animationinterpolationtime, 0, 150, 1000); + +model *loadingmodel = NULL; + +#include "tristrip.h" +#include "vertmodel.h" +#include "md2.h" +#include "md3.h" + +#define checkmdl if(!loadingmodel) { conoutf("not loading a model"); return; } + +void mdlscale(int percent) +{ + checkmdl; + float scale = 0.3f; + if(percent>0) scale = percent/100.0f; + else if(percent<0) scale = 0.0f; + loadingmodel->scale = scale; +}; + +COMMAND(mdlscale, ARG_1INT); + +void mdltrans(char *x, char *y, char *z) +{ + checkmdl; + loadingmodel->translate = vec(atof(x), atof(y), atof(z)); +}; + +COMMAND(mdltrans, ARG_3STR); + +vector mapmodels; + +void mapmodel(char *rad, char *h, char *zoff, char *snap, char *name) +{ + mapmodelinfo &mmi = mapmodels.add(); + mmi.rad = atoi(rad); + mmi.h = atoi(h); + mmi.zoff = atoi(zoff); + s_sprintf(mmi.name)("mapmodels/%s", name); +}; + +void mapmodelreset() { mapmodels.setsize(0); }; + +mapmodelinfo &getmminfo(int i) { return mapmodels.inrange(i) ? mapmodels[i] : *(mapmodelinfo *)0; }; + +COMMAND(mapmodel, ARG_5STR); +COMMAND(mapmodelreset, ARG_NONE); + +hashtable mdllookup; + +model *loadmodel(const char *name, int i = -1) +{ + if(!name) + { + if(!mapmodels.inrange(i)) return NULL; + mapmodelinfo &mmi = mapmodels[i]; + if(mmi.m) return mmi.m; + name = mmi.name; + }; + model **mm = mdllookup.access(name); + model *m; + if(mm) m = *mm; + else + { + m = new md2(name); + loadingmodel = m; + if(!m->load()) + { + delete m; + m = new md3(name); + loadingmodel = m; + if(!m->load()) + { + delete m; + loadingmodel = NULL; + return NULL; + }; + }; + loadingmodel = NULL; + mdllookup.access(m->name(), &m); + }; + if(mapmodels.inrange(i) && !mapmodels[i].m) mapmodels[i].m = m; + return m; +}; + +void rendermodel(char *mdl, int anim, int tex, float rad, float x, float y, float z, float yaw, float pitch, float speed, int basetime, dynent *d, char *vwepmdl, float scale) +{ + model *m = loadmodel(mdl); + if(!m) return; + + if(rad > 0 && isoccluded(player1->o.x, player1->o.y, x-rad, z-rad, rad*2)) return; + + int ix = (int)x; + int iy = (int)z; + vec light(1, 1, 1); + + if(!OUTBORD(ix, iy)) + { + sqr *s = S(ix,iy); + float ll = 256.0f; // 0.96f; + float of = 0.0f; // 0.1f; + light.x = s->r/ll+of; + light.y = s->g/ll+of; + light.z = s->b/ll+of; + }; + + glColor3fv(&light.x); + m->setskin(tex); + + model *vwep = NULL; + if(vwepmdl) + { + vwep = loadmodel(vwepmdl); + if(vwep->type()!=m->type()) vwep = NULL; + }; + + if(anim&ANIM_MIRROR) glCullFace(GL_BACK); + m->render(anim, (int)(size_t)d, speed, basetime, x, y, z, yaw, pitch, d, vwep, scale); + if(anim&ANIM_MIRROR) glCullFace(GL_FRONT); +}; + +int findanim(const char *name) +{ + const char *names[] = { "idle", "run", "attack", "pain", "jump", "land", "flipoff", "salute", "taunt", "wave", "point", "crouch idle", "crouch walk", "crouch attack", "crouch pain", "crouch death", "death", "lying dead", "flag", "gun idle", "gun shoot", "gun reload", "gun throw", "mapmodel", "trigger", "all" }; + loopi(sizeof(names)/sizeof(names[0])) if(!strcmp(name, names[i])) return i; + return -1; +}; + +void loadskin(const char *dir, const char *altdir, Texture *&skin, model *m) // model skin sharing +{ + #define ifnoload if((skin = textureload(path))==crosshair) + s_sprintfd(path)("packages/models/%s/skin.jpg", dir); + ifnoload + { + strcpy(path+strlen(path)-3, "png"); + ifnoload + { + s_sprintf(path)("packages/models/%s/skin.jpg", altdir); + ifnoload + { + strcpy(path+strlen(path)-3, "png"); + ifnoload return; + }; + }; + }; +}; + +void preload_mapmodels() +{ + int xs, ys; + loopv(ents) + { + entity &e = ents[i]; + if(e.type!=MAPMODEL || !mapmodels.inrange(e.attr2)) continue; + if(!loadmodel(NULL, e.attr2)) continue; + if(e.attr4) lookuptexture(e.attr4, xs, ys); + }; +}; + diff --git a/source/src/renderparticles.cpp b/source/src/renderparticles.cpp index 7260f6c6..a80907e5 100644 --- a/source/src/renderparticles.cpp +++ b/source/src/renderparticles.cpp @@ -47,7 +47,7 @@ void render_particles(int time) { if(demoplayback && demotracking) { - vec nom = { 0, 0, 0 }; + vec nom(0, 0, 0); newparticle(player1->o, nom, 100000000, 4); }; @@ -141,7 +141,7 @@ void particle_splash(int type, int num, int fade, vec &p) z = rnd(radius*2)-radius; } while(x*x+y*y+z*z>radius*radius); - vec d = { (float)x, (float)y, (float)z }; + vec d((float)x, (float)y, (float)z); newparticle(p, d, rnd(fade*3), type); }; }; @@ -155,7 +155,7 @@ void particle_trail(int type, int fade, vec &s, vec &e) loopi((int)d*2) { p.add(v); - vec d = { float(rnd(11)-5), float(rnd(11)-5), float(rnd(11)-5) }; + vec d(float(rnd(11)-5), float(rnd(11)-5), float(rnd(11)-5)); newparticle(p, d, rnd(fade)+fade, type); }; }; diff --git a/source/src/savegamedemo.cpp b/source/src/savegamedemo.cpp index 231e74f1..db97b623 100644 --- a/source/src/savegamedemo.cpp +++ b/source/src/savegamedemo.cpp @@ -8,7 +8,7 @@ gzFile f = NULL; bool demorecording = false; bool demoplayback = false; bool demoloading = false; -dvector playerhistory; +vector playerhistory; int democlientnum = 0; void startdemo(); @@ -33,7 +33,7 @@ void stop() demorecording = false; demoplayback = false; demoloading = false; - loopv(playerhistory) zapdynent(playerhistory[i]); + loopv(playerhistory) zapplayer(playerhistory[i]); playerhistory.setsize(0); // Added by Rick: Remove bots loopv(bots) @@ -41,7 +41,7 @@ void stop() if (!bots[i]) continue; delete bots[i]->pBot; bots[i]->pBot = NULL; - zapdynent(bots[i]); + DELETEP(bots[i]); } bots.setsize(0); }; @@ -198,7 +198,7 @@ void stopreset() { conoutf("demo stopped (%d msec elapsed)", lastmillis-starttime); stop(); - loopv(players) zapdynent(players[i]); + loopv(players) zapplayer(players[i]); disconnect(0, 0); }; @@ -263,7 +263,7 @@ void demoplaybackstep() gzread(f, buf, len); localservertoclient(chan, buf, len); // update game state - dynent *target = players[democlientnum]; + playerent *target = (playerent *)players[democlientnum]; ASSERT(target); int extras; @@ -287,13 +287,13 @@ void demoplaybackstep() // insert latest copy of player into history if(extras && (playerhistory.empty() || playerhistory.last()->lastupdate!=playbacktime)) { - dynent *d = newdynent(); + playerent *d = newplayerent(); *d = *target; d->lastupdate = playbacktime; playerhistory.add(d); if(playerhistory.length()>20) { - zapdynent(playerhistory[0]); + zapplayer(playerhistory[0]); playerhistory.remove(0); }; }; @@ -306,10 +306,10 @@ void demoplaybackstep() int itime = lastmillis-demodelaymsec; loopvrev(playerhistory) if(playerhistory[i]->lastupdateo); } diff --git a/source/src/tools.cpp b/source/src/tools.cpp index d7e9d7a6..21bbe814 100644 --- a/source/src/tools.cpp +++ b/source/src/tools.cpp @@ -12,6 +12,16 @@ char *path(char *s) return s; }; +char *parentdir(char *directory) +{ + char *p = strrchr(directory, '/'); + if(!p) p = directory; + size_t len = p-directory+1; + char *parent = new char[len]; + s_strncpy(parent, directory, len); + return parent; +}; + char *loadfile(char *fn, int *size) { FILE *f = fopen(fn, "rb"); diff --git a/source/src/tools.h b/source/src/tools.h index 4085a273..ffac7b13 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -157,6 +157,13 @@ template struct vector return buf[ulen++]; }; + T &dup() + { + if(ulen==alen) vrealloc(); + new (&buf[ulen]) T(buf[ulen-1]); + return buf[ulen++]; + }; + bool inrange(size_t i) const { return i=0 && i struct vector loopi(ulen) if(buf[i]==o) remove(i--); }; + void replacewithlast(const T &o) + { + if(!ulen) return; + loopi(ulen-1) if(buf[i]==o) + { + buf[i] = buf[ulen-1]; + }; + ulen--; + }; + T &insert(int i, const T &e) { add(T()); diff --git a/source/src/tristrip.h b/source/src/tristrip.h new file mode 100644 index 00000000..75a6d3e4 --- /dev/null +++ b/source/src/tristrip.h @@ -0,0 +1,270 @@ +VAR(dbgts, 0, 0, 1); +VAR(tsswap, 0, 1, 1); + +struct tristrip +{ + enum + { + // must be larger than all other triangle/vert indices + UNUSED = 0xFFFE, + REMOVED = 0xFFFF + }; + + enum + { + // must be larger than all other vert indices + RESTART = 0xFFFE, + LIST = 0xFFFF + }; + + struct triangle + { + ushort v[3], n[3]; + + bool link(ushort neighbor, ushort old = UNUSED) + { + loopi(3) + { + if(n[i]==neighbor) return false; + else if(n[i]==old) { n[i] = neighbor; return true; }; + }; + if(dbgts && old==UNUSED) conoutf("excessive links"); + return false; + }; + + void unlink(ushort neighbor, ushort unused = UNUSED) + { + loopi(3) if(n[i]==neighbor) n[i] = unused; + }; + + int numlinks() const { int num = 0; loopi(3) if(n[i] triangles; + vector connectivity[4]; + vector nodes; + + void addtriangles(const ushort *triidxs, int numtris) + { + if(dbgts) conoutf("addtriangles: tris = %d, inds = %d", numtris, numtris*3); + loopi(numtris) + { + triangle &tri = triangles.add(); + loopj(3) + { + tri.v[j] = *triidxs++; + tri.n[j] = UNUSED; + }; + if(tri.v[0]==tri.v[1] || tri.v[1]==tri.v[2] || tri.v[2]==tri.v[0]) + { + if(dbgts) conoutf("degenerate triangle"); + triangles.drop(); + }; + }; + }; + + struct edge + { + ushort from, to; + + edge() {}; + edge(ushort from, ushort to) : from(min(from, to)), to(max(from, to)) {}; + + void link(ushort tri) + { + if(tri < from) + { + to = from; + from = tri; + } + else to = tri; + }; + }; + + void findconnectivity() + { + hashtable edges; + nodes.setsizenodelete(0); + loopv(triangles) + { + triangle &tri = triangles[i]; + loopj(3) + { + while(nodes.length()<=tri.v[j]) nodes.add(0); + nodes[tri.v[j]]++; + + edge e(tri.v[j], tri.v[j==2 ? 0 : j+1]); + ushort *owner = edges.access(e); + if(!owner) edges[e] = i; + else if(!tri.link(*owner)) + { + if(dbgts) conoutf("failed linkage 1: %d -> %d", *owner, i); + } + else if(!triangles[*owner].link(i)) + { + if(dbgts) conoutf("failed linkage 2: %d -> %d", *owner, i); + tri.unlink(*owner); + }; + }; + }; + loopi(4) connectivity[i].setsizenodelete(0); + loopv(triangles) connectivity[triangles[i].numlinks()].add(i); + if(dbgts) conoutf("no connections: %d", connectivity[0].length()); + }; + + void removeconnectivity(ushort i) + { + triangle &tri = triangles[i]; + loopj(3) if(tri.n[j] nodes[v1] ? 1 : -1; + } + else score += nodes[v1] > nodes[v2] ? 1 : -1; + if(!tsswap && swap) continue; + score += swap ? 1 : -1; + }; + if(score < nextscore) { next = tri.n[i]; nextswap = swap; nextscore = score; }; + }; + if(next!=UNUSED) + { + tri.unlink(next, REMOVED); + connectivity[triangles[next].numlinks()].replacewithlast(next); + removeconnectivity(next); + }; + return next; + }; + + void buildstrip(vector &strip, bool reverse = false) + { + ushort prev = leastconnected(); + if(prev==UNUSED) return; + triangle &first = triangles[prev]; + bool doswap; + ushort cur = nexttriangle(first, doswap); + if(cur==UNUSED) + { + loopi(3) strip.add(first.v[reverse && i>=1 ? 3-i : i]); + return; + }; + int from = findedge(first, triangles[cur]), + to = findedge(first, triangles[cur], first.v[from]); + if(from+1!=to) swap(int, from, to); + strip.add(first.v[(to+1)%3]); + if(reverse) swap(int, from, to); + strip.add(first.v[from]); + strip.add(first.v[to]); + + ushort v1 = first.v[to], v2 = first.v[from]; + while(cur!=UNUSED) + { + prev = cur; + cur = nexttriangle(triangles[prev], doswap, v1, v2); + if(doswap) strip.add(v2); + ushort v = triangles[prev].diffvert(v1, v2); + strip.add(v); + if(!doswap) v2 = v1; + v1 = v; + }; + }; + + void buildstrips(vector &strips, bool prims = true, bool degen = false) + { + vector singles; + findconnectivity(); + int numtris = 0, numstrips = 0; + while(remaining()) + { + vector strip; + bool reverse = degen && !strips.empty() && (strips.length()&1); + buildstrip(strip, reverse); + numstrips++; + numtris += strip.length()-2; + if(strip.length()==3 && prims) + { + loopv(strip) singles.add(strip[i]); + continue; + }; + if(!strips.empty()) + { + if(degen) { strips.dup(); strips.add(strip[0]); } + else strips.add(RESTART); + }; + loopv(strip) strips.add(strip[i]); + }; + if(prims && !singles.empty()) + { + strips.add(LIST); + loopv(singles) strips.add(singles[i]); + }; + if(dbgts) conoutf("strips = %d, tris = %d, inds = %d, merges = %d", numstrips, numtris, numtris + numstrips*2, (degen ? 2 : 1)*(numstrips-1)); + }; + +}; + +static inline uint hthash(const tristrip::edge &x) { return x.from^x.to; }; +static inline bool htcmp(const tristrip::edge &x, const tristrip::edge &y) { return x.from==y.from && x.to==y.to; }; + diff --git a/source/src/vertmodel.h b/source/src/vertmodel.h new file mode 100644 index 00000000..7404de71 --- /dev/null +++ b/source/src/vertmodel.h @@ -0,0 +1,404 @@ +struct vertmodel : model +{ + struct anpos + { + int fr1, fr2; + float t; + + void setframes(const animstate &as) + { + int time = lastmillis-as.basetime; + fr1 = (int)(time/as.speed); // round to full frames + t = (time-fr1*as.speed)/as.speed; // progress of the frame, value from 0.0f to 1.0f + if(as.anim&ANIM_LOOP) + { + fr1 = fr1%as.range+as.frame; + fr2 = fr1+1; + if(fr2>=as.frame+as.range) fr2 = as.frame; + } + else + { + fr1 = min(fr1, as.range-1)+as.frame; + fr2 = min(fr1+1, as.frame+as.range-1); + }; + if(as.anim&ANIM_REVERSE) + { + fr1 = (as.frame+as.range-1)-(fr1-as.frame); + fr2 = (as.frame+as.range-1)-(fr2-as.frame); + }; + }; + }; + + struct tcvert { float u, v; ushort index; }; + struct tri { ushort vert[3]; }; + + struct mesh + { + char *name; + vec *verts; + tcvert *tcverts; + tri *tris; + int numverts, numtcverts, numtris; + + Texture *skin; + int tex; + + vec *dynbuf; + ushort *dynidx; + int dynframe, dynlen; + GLuint statlist; + int statlen; + + mesh() : name(0), verts(0), tcverts(0), tris(0), skin(crosshair), tex(0), dynbuf(0), dynidx(0), dynframe(-1), statlist(0) {}; + + ~mesh() + { + DELETEA(name); + DELETEA(verts); + DELETEA(tcverts); + DELETEA(tris); + if(statlist) glDeleteLists(statlist, 1); + DELETEA(dynidx); + DELETEA(dynbuf); + }; + + void gendyn() + { + tristrip ts; + ts.addtriangles(tris->vert, numtris); + vector idxs; + ts.buildstrips(idxs); + dynbuf = new vec[numverts]; + dynidx = new ushort[idxs.length()]; + memcpy(dynidx, idxs.getbuf(), idxs.length()*sizeof(ushort)); + dynlen = idxs.length(); + }; + + void gendynverts(anpos &cur, anpos *prev, float ai_t) + { + vec *vert1 = &verts[cur.fr1 * numverts], + *vert2 = &verts[cur.fr2 * numverts], + *pvert1 = NULL, *pvert2 = NULL; + if(prev) + { + pvert1 = &verts[prev->fr1 * numverts]; + pvert2 = &verts[prev->fr2 * numverts]; + dynframe = -1; + } + else if(cur.fr1==cur.fr2) + { + if(cur.fr1==dynframe) return; + dynframe = cur.fr1; + } + else dynframe = -1; + loopi(numverts) // vertices + { + vec &v = dynbuf[i]; + #define ip(p1, p2, t) (p1+t*(p2-p1)) + #define ip_v(p, c, t) ip(p##1[i].c, p##2[i].c, t) + if(prev) + { + #define ip_v_ai(c) ip( ip_v(pvert, c, prev->t), ip_v(vert, c, cur.t), ai_t) + v = vec(ip_v_ai(x), ip_v_ai(y), ip_v_ai(z)); + #undef ip_v_ai + } + else + { + v = vec(ip_v(vert, x, cur.t), ip_v(vert, y, cur.t), ip_v(vert, z, cur.t)); + }; + #undef ip + #undef ip_v + }; + }; + + void render(animstate &as, anpos &cur, anpos *prev, float ai_t, float scale) + { + if(!dynbuf) return; + + int id = skin->id; + if(tex) + { + int xs, ys; + id = lookuptexture(tex, xs, ys); + }; + glBindTexture(GL_TEXTURE_2D, id); + + if(as.anim&ANIM_MIRROR || scale!=1) + { + glPushMatrix(); + glScalef(as.anim&ANIM_MIRROR ? -scale : scale, scale, scale); + }; + bool isstat = as.frame==0 && as.range==1; + if(isstat && statlist) + { + glCallList(statlist); + xtraverts += statlen; + } + else + { + if(isstat) glNewList(statlist = glGenLists(1), GL_COMPILE); + gendynverts(cur, prev, ai_t); + loopj(dynlen) + { + ushort index = dynidx[j]; + if(index>=tristrip::RESTART || !j) + { + if(j) glEnd(); + glBegin(index==tristrip::LIST ? GL_TRIANGLES : GL_TRIANGLE_STRIP); + if(index>=tristrip::RESTART) continue; + }; + tcvert &tc = tcverts[index]; + glTexCoord2f(tc.u, tc.v); + glVertex3fv(&dynbuf[tc.index].x); + }; + glEnd(); + if(isstat) + { + glEndList(); + glCallList(statlist); + statlen = dynlen; + }; + xtraverts += dynlen; + }; + if(as.anim&ANIM_MIRROR || scale!=1) glPopMatrix(); + }; + }; + + struct animinfo + { + int frame, range; + float speed; + }; + + struct tag + { + char *name; + vec pos; + float transform[3][3]; + + tag() : name(NULL) {}; + ~tag() { DELETEA(name); }; + }; + + struct part + { + bool loaded; + vertmodel *model; + int index, numframes; + vector meshes; + vector *anims; + part **links; + tag *tags; + int numtags; + + part() : loaded(false), anims(NULL), links(NULL), tags(NULL), numtags(0) {}; + virtual ~part() + { + meshes.deletecontentsp(); + DELETEA(anims); + DELETEA(links); + DELETEA(tags); + }; + + bool link(part *link, const char *tag) + { + loopi(numtags) if(!strcmp(tags[i].name, tag)) + { + links[i] = link; + return true; + }; + return false; + }; + + void scaleverts(const float scale, const vec &translate) + { + loopv(meshes) + { + mesh &m = *meshes[i]; + loopj(numframes*m.numverts) + { + vec &v = m.verts[j]; + if(!index) v.add(translate); + v.mul(scale); + }; + }; + loopi(numframes*numtags) + { + vec &v = tags[i].pos; + if(!index) v.add(translate); + v.mul(scale); + }; + }; + + void gendyn() + { + loopv(meshes) meshes[i]->gendyn(); + }; + + virtual void getdefaultanim(animstate &as, int anim, int varseed, float speed) + { + as.frame = 0; + as.range = 1; + as.speed = speed; + }; + + bool calcanimstate(int anim, int varseed, float speed, int basetime, dynent *d, animstate &as) + { + as.anim = anim; + as.basetime = basetime; + if((anim&ANIM_INDEX)==ANIM_ALL) + { + as.frame = 0; + as.range = numframes; + } + else if(anims) + { + vector &ais = anims[anim&ANIM_INDEX]; + if(ais.length()) + { + animinfo &ai = ais[varseed%ais.length()]; + as.frame = ai.frame; + as.range = ai.range; + as.speed = speed*100.0f/ai.speed; + } + else + { + as.frame = 0; + as.range = 1; + as.speed = speed; + }; + } + else getdefaultanim(as, anim&ANIM_INDEX, varseed, speed); + if(anim&(ANIM_START|ANIM_END)) + { + if(anim&ANIM_END) as.frame += as.range-1; + as.range = 1; + }; + + if(as.frame+as.range>numframes) + { + if(as.frame>=numframes) return false; + as.range = numframes-as.frame; + }; + + if(d && index<2) + { + if(d->lastmodel[index]!=this || d->lastanimswitchtime[index]==-1) + { + d->current[index] = as; + d->lastanimswitchtime[index] = lastmillis-animationinterpolationtime*2; + } + else if(d->current[index] != as) + { + if(lastmillis-d->lastanimswitchtime[index]>animationinterpolationtime/2) d->prev[index] = d->current[index]; + d->current[index] = as; + d->lastanimswitchtime[index] = lastmillis; + }; + d->lastmodel[index] = this; + }; + return true; + }; + + void render(int anim, int varseed, float speed, int basetime, dynent *d, float scale) + { + if(meshes.length() <= 0) return; + animstate as; + if(!calcanimstate(anim, varseed, speed, basetime, d, as)) return; + + if(!meshes[0]->dynbuf) gendyn(); + + anpos prev, cur; + cur.setframes(d && index<2 ? d->current[index] : as); + + float ai_t = 0; + bool doai = !(anim&ANIM_NOINTERP) && d && index<2 && lastmillis-d->lastanimswitchtime[index]prev[index]); + ai_t = (lastmillis-d->lastanimswitchtime[index])/(float)animationinterpolationtime; + }; + + loopv(meshes) meshes[i]->render(as, cur, doai ? &prev : NULL, ai_t, scale); + + loopi(numtags) if(links[i]) // render the linked models - interpolate rotation and position of the 'link-tags' + { + part *link = links[i]; + + GLfloat matrix[16]; + tag *tag1 = &tags[cur.fr1*numtags+i]; + tag *tag2 = &tags[cur.fr2*numtags+i]; + #define ip(p1, p2, t) (p1+t*(p2-p1)) + #define ip_ai_tag(c) ip( ip( tag1p->c, tag2p->c, prev.t), ip( tag1->c, tag2->c, cur.t), ai_t) + if(doai) + { + tag *tag1p = &tags[prev.fr1 * numtags + i]; + tag *tag2p = &tags[prev.fr2 * numtags + i]; + loopj(3) matrix[j] = ip_ai_tag(transform[0][j]); // transform + loopj(3) matrix[4 + j] = ip_ai_tag(transform[1][j]); + loopj(3) matrix[8 + j] = ip_ai_tag(transform[2][j]); + loopj(3) matrix[12 + j] = scale*ip_ai_tag(pos[j]); // position + } + else + { + loopj(3) matrix[j] = ip(tag1->transform[0][j], tag2->transform[0][j], cur.t); // transform + loopj(3) matrix[4 + j] = ip(tag1->transform[1][j], tag2->transform[1][j], cur.t); + loopj(3) matrix[8 + j] = ip(tag1->transform[2][j], tag2->transform[2][j], cur.t); + loopj(3) matrix[12 + j] = scale*ip(tag1->pos[j], tag2->pos[j], cur.t); // position + }; + #undef ip_ai_tag + #undef ip + matrix[3] = matrix[7] = matrix[11] = 0.0f; + matrix[15] = 1.0f; + glPushMatrix(); + glMultMatrixf(matrix); + link->render(anim, varseed, speed, basetime, d, scale); + glPopMatrix(); + }; + }; + + void setanim(int num, int frame, int range, float speed) + { + if(frame<0 || frame>=numframes || range<=0 || frame+range>numframes) + { + conoutf("invalid frame %d, range %d in model %s", frame, range, model->loadname); + return; + }; + if(!anims) anims = new vector[NUMANIMS]; + animinfo &ai = anims[num].add(); + ai.frame = frame; + ai.range = range; + ai.speed = speed; + }; + }; + + bool loaded; + char *loadname; + vector parts; + + vertmodel(const char *name) : loaded(false) + { + loadname = newstring(name); + }; + + ~vertmodel() + { + delete[] loadname; + parts.deletecontentsp(); + }; + + char *name() { return loadname; }; + + bool link(part *link, const char *tag) + { + loopv(parts) if(parts[i]->link(link, tag)) return true; + return false; + }; + + void setskin(int tex) + { + if(parts.length()!=1 || parts[0]->meshes.length()!=1) return; + mesh &m = *parts[0]->meshes[0]; + m.tex = tex; + }; +}; + diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index ba41610b..2b724a9d 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -112,7 +112,7 @@ void altaction(int activate) COMMAND(altaction, ARG_1INT); -void reload(dynent *d) +void reload(playerent *d) { if(!d || d->reloading || d->weaponchanging) return; if(d == player1) setscope(false); @@ -145,7 +145,7 @@ void reload(dynent *d) } if(akimbo) playsoundc(S_RAKIMBO); - else if(d->bIsBot) playsound(guns[d->gunselect].reload, &d->o); + else if(d->type==ENT_BOT) playsound(guns[d->gunselect].reload, &d->o); else playsoundc(guns[d->gunselect].reload); }; @@ -165,7 +165,7 @@ void createrays(vec &from, vec &to) // create random spread of rays loopi(SGRAYS) { #define RNDD (rnd(101)-50)*f - vec r = { RNDD, RNDD, RNDD }; + vec r(RNDD, RNDD, RNDD); sg[i] = to; sg[i].add(r); #undef RNDD @@ -201,24 +201,24 @@ bool intersect(dynent *d, vec &from, vec &to, vec *end) // if lineseg hits ent && p->z >= d->o.z-d->eyeheight; }; -dynent *playerincrosshair() +playerent *playerincrosshair() { if(demoplayback) return NULL; loopv(players) { - dynent *o = players[i]; + playerent *o = players[i]; if(!o) continue; if(intersect(o, player1->o, worldpos)) return o; }; return NULL; }; // Added by Rick -dynent *botincrosshair() +botent *botincrosshair() { if(demoplayback) return NULL; loopv(bots) { - dynent *o = bots[i]; + botent *o = bots[i]; if(!o) continue; if(intersect(o, player1->o, worldpos)) return o; }; @@ -227,12 +227,12 @@ dynent *botincrosshair() // End add by Rick const int MAXPROJ = 100; -struct projectile { vec o, to; float speed; dynent *owner; int gun; bool inuse, local; }; +struct projectile { vec o, to; float speed; playerent *owner; int gun; bool inuse, local; }; projectile projs[MAXPROJ]; void projreset() { loopi(MAXPROJ) projs[i].inuse = false; }; -void newprojectile(vec &from, vec &to, float speed, bool local, dynent *owner, int gun) +void newprojectile(vec &from, vec &to, float speed, bool local, playerent *owner, int gun) { loopi(MAXPROJ) { @@ -249,33 +249,35 @@ void newprojectile(vec &from, vec &to, float speed, bool local, dynent *owner, i }; }; -void hit(int target, int damage, dynent *d, dynent *at, bool gib=false) +void hit(int target, int damage, playerent *d, playerent *at, bool gib=false) { if(d==player1) selfdamage(damage, at==player1 ? -1 : -2, at, gib); - //else if(d->monsterstate) monsterpain(d, damage, at); // Added by Rick: Let bots take damage - else if(d->pBot) d->pBot->BotPain(damage, at, gib); - else if(d->bIsBot) + else if(d->type==ENT_BOT) { - int PlayerIndex = -1; - if (at->bIsBot) PlayerIndex = BotManager.GetBotIndex(at); + if(((botent *)d)->pBot) ((botent *)d)->pBot->BotPain(damage, at, gib); else { - loopv(players) - { - if (!players[i]) continue; + int PlayerIndex = -1; + if (at->type==ENT_BOT) PlayerIndex = BotManager.GetBotIndex((botent *)at); + else + { + loopv(players) + { + if (!players[i]) continue; - if (players[i] == at) - { - PlayerIndex = i; - break; - } - } - } - - int msgtype = (at->bIsBot) ? SV_BOT2BOTDMG : SV_CLIENT2BOTDMG; - addmsg(msgtype, "ri3", BotManager.GetBotIndex(d), damage, PlayerIndex); - playsound(S_PAIN1+rnd(5), &d->o); + if (players[i] == at) + { + PlayerIndex = i; + break; + } + } + } + + int msgtype = (at->type==ENT_BOT) ? SV_BOT2BOTDMG : SV_CLIENT2BOTDMG; + addmsg(msgtype, "ri3", BotManager.GetBotIndex((botent *)d), damage, PlayerIndex); + playsound(S_PAIN1+rnd(5), &d->o); + }; } // End add by Rick //else { addmsg(SV_DAMAGE, "ri3", target, damage, d->lifesequence); playsound(S_PAIN1+rnd(5), &d->o); }; Modified by Rick: Added IsBot and PlayerIndex to message @@ -283,8 +285,8 @@ void hit(int target, int damage, dynent *d, dynent *at, bool gib=false) { // Modified by Rick: Added IsBot and PlayerIndex to message int PlayerIndex = -1; - if (at->bIsBot) - PlayerIndex = BotManager.GetBotIndex(at); + if (at->type==ENT_BOT) + PlayerIndex = BotManager.GetBotIndex((botent *)at); else { loopv(players) @@ -299,7 +301,7 @@ void hit(int target, int damage, dynent *d, dynent *at, bool gib=false) } } } - if(at->bIsBot) addmsg(SV_BOT2CLIENTDMG, "ri4", target, damage, d->lifesequence, PlayerIndex); + if(at->type==ENT_BOT) addmsg(SV_BOT2CLIENTDMG, "ri4", target, damage, d->lifesequence, PlayerIndex); else addmsg(gib ? SV_GIBDAMAGE : SV_DAMAGE, "ri3", target, damage, d->lifesequence); playsound(S_PAIN1+rnd(5), &d->o); }; @@ -311,7 +313,7 @@ void hit(int target, int damage, dynent *d, dynent *at, bool gib=false) const float RL_RADIUS = 7; const float RL_DAMRAD = 10; // hack -void radialeffect(dynent *o, vec &v, int cn, int qdam, dynent *at) +void radialeffect(playerent *o, vec &v, int cn, int qdam, playerent *at) { if(o->state!=CS_ALIVE) return; vec temp; @@ -346,7 +348,7 @@ void splash(projectile *p, vec &v, vec &vold, int notthisplayer, int notthismons loopv(players) { if(i==notthisplayer) continue; - dynent *o = players[i]; + playerent *o = players[i]; if(!o) continue; radialeffect(o, v, i, qdam, p->owner); }; @@ -354,7 +356,7 @@ void splash(projectile *p, vec &v, vec &vold, int notthisplayer, int notthismons loopv(bots) { if(i==notthisbot) continue; - dynent *o = bots[i]; + botent *o = bots[i]; if(!o) continue; radialeffect(o, v, i, qdam, p->owner); } @@ -366,7 +368,7 @@ void splash(projectile *p, vec &v, vec &vold, int notthisplayer, int notthismons // Modified by Rick // inline void projdamage(dynent *o, projectile *p, vec &v, int i, int im, int qdam) -inline void projdamage(dynent *o, projectile *p, vec &v, int i, int im, int ib, int qdam) +inline void projdamage(playerent *o, projectile *p, vec &v, int i, int im, int ib, int qdam) { if(o->state!=CS_ALIVE) return; if(intersect(o, p->o, v)) @@ -394,7 +396,7 @@ void moveprojectiles(float time) { loopv(players) { - dynent *o = players[i]; + playerent *o = players[i]; if(!o) continue; // projdamage(o, p, v, i, -1, qdam); Modified by Rick projdamage(o, p, v, i, -1, -1, qdam); @@ -402,7 +404,7 @@ void moveprojectiles(float time) // Added by Rick: Damage bots aswell loopv(bots) { - dynent *o = bots[i]; + botent *o = bots[i]; if(!o || (o == p->owner)) continue; projdamage(o, p, v, -1, -1, i, qdam); }; @@ -432,17 +434,12 @@ void moveprojectiles(float time) }; }; -void throw_nade(dynent *d, vec &to, physent *p) +void throw_nade(playerent *d, vec &to, bounceent *p) { if(!p || !d) return; playsound(S_GRENADETHROW); - p->isphysent = true; - p->gravity = 20; - p->state = NADE_THROWED; - - p->timeinair = 0; - p->onfloor = false; + p->bouncestate = NADE_THROWED; p->o = d->o; p->vel.z = sinf(RAD*d->pitch); @@ -467,13 +464,13 @@ void throw_nade(dynent *d, vec &to, physent *p) }; }; -physent *new_nade(dynent *d, int millis = 0) +bounceent *new_nade(playerent *d, int millis = 0) { - physent *p = new_physent(); + bounceent *p = newbounceent(); p->owner = d; p->millis = lastmillis; p->timetolife = 2000-millis; - p->state = NADE_ACTIVATED; + p->bouncestate = NADE_ACTIVATED; d->inhandnade = p; d->thrownademillis = 0; @@ -481,11 +478,11 @@ physent *new_nade(dynent *d, int millis = 0) return p; }; -void explode_nade(physent *i) +void explode_nade(bounceent *i) { if(!i) return; - if(i->state != NADE_THROWED) + if(i->bouncestate != NADE_THROWED) { vec o = i->owner->o; o.add(0.1f); @@ -495,7 +492,7 @@ void explode_nade(physent *i) newprojectile(i->o, i->o, 1, i->owner==player1, i->owner, GUN_GRENADE); }; -void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nademillis) // create visual effect from a shot +void shootv(int gun, vec &from, vec &to, playerent *d, bool local, int nademillis) // create visual effect from a shot { playsound(guns[gun].sound, d==player1 ? NULL : &d->o); switch(gun) @@ -523,7 +520,7 @@ void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nademillis) { /*int nademillis = nadetimer/100*nadepercent; if(nademillis<0 || nademillis>100) nademillis = 100;*/ - physent *p = new_nade(d, nademillis); + bounceent *p = new_nade(d, nademillis); throw_nade(d, to, p); } }; @@ -537,7 +534,7 @@ void shootv(int gun, vec &from, vec &to, dynent *d, bool local, int nademillis) }; }; -void hitpush(int target, int damage, dynent *d, dynent *at, vec &from, vec &to) +void hitpush(int target, int damage, playerent *d, playerent *at, vec &from, vec &to) { hit(target, damage, d, at, at->gunselect==GUN_KNIFE ? true : false); vec v; @@ -546,7 +543,7 @@ void hitpush(int target, int damage, dynent *d, dynent *at, vec &from, vec &to) d->vel.add(v); }; -void raydamage(dynent *o, vec &from, vec &to, dynent *d, int i) +void raydamage(playerent *o, vec &from, vec &to, playerent *d, int i) { if(o->state!=CS_ALIVE) return; int qdam = guns[d->gunselect].damage; @@ -560,7 +557,7 @@ void raydamage(dynent *o, vec &from, vec &to, dynent *d, int i) else if(intersect(o, from, to)) hitpush(i, qdam, o, d, from, to); }; -void spreadandrecoil(vec &from, vec &to, dynent *d) +void spreadandrecoil(vec &from, vec &to, playerent *d) { //nothing special for a knife if (d->gunselect==GUN_KNIFE || d->gunselect==GUN_GRENADE) return; @@ -590,7 +587,7 @@ void spreadandrecoil(vec &from, vec &to, dynent *d) if(d->gunselect!=GUN_SHOTGUN) //no spread on shotgun { #define RNDD (rnd(spd)-spd/2)*f - vec r = { RNDD, RNDD, RNDD }; + vec r(RNDD, RNDD, RNDD); to.add(r); #undef RNDD }; @@ -601,11 +598,11 @@ void spreadandrecoil(vec &from, vec &to, dynent *d) if(d->pitch<80.0f) d->pitch += guns[d->gunselect].recoil*0.05f; }; -bool hasammo(dynent *d) // bot mod +bool hasammo(playerent *d) // bot mod { if(!d->mag[d->gunselect]) { - if (d->bIsBot) botplaysound(S_NOAMMO, d); + if (d->type==ENT_BOT) botplaysound(S_NOAMMO, (botent *)d); else playsoundc(S_NOAMMO); d->gunwait = 250; d->lastattackgun = -1; @@ -616,7 +613,7 @@ bool hasammo(dynent *d) // bot mod const int grenadepulltime = 650; bool akimboside = false; -void shoot(dynent *d, vec &targ) +void shoot(playerent *d, vec &targ) { int attacktime = lastmillis-d->lastaction; @@ -702,7 +699,7 @@ void shoot(dynent *d, vec &targ) loopv(players) { - dynent *o = players[i]; + playerent *o = players[i]; if(!o) continue; raydamage(o, from, to, d, i); }; @@ -710,11 +707,11 @@ void shoot(dynent *d, vec &targ) // Added by Rick: raydamage on bots too loopv(bots) { - dynent *o = bots[i]; + botent *o = bots[i]; if(!o || (o == d)) continue; raydamage(o, from, to, d, i); }; // End add by Rick - if(d->bIsBot) raydamage(player1, from, to, d, -1); + if(d->type==ENT_BOT) raydamage(player1, from, to, d, -1); }; diff --git a/source/src/world.cpp b/source/src/world.cpp index 76b06f78..37b19faf 100644 --- a/source/src/world.cpp +++ b/source/src/world.cpp @@ -175,7 +175,7 @@ int closestent() // used for delent and edit mode ent display { entity &e = ents[i]; if(e.type==NOTUSED) continue; - vec v = { e.x, e.y, e.z }; + vec v(e.x, e.y, e.z); float dist = v.dist(player1->o); if(distmonsterstate) reach = reach/2; if(!reach) return; int creach = reach+16; // dependant on lightray random offsets!