Forum

self.touch For Player?

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

self.touch For Player?

Postby Junrall » Thu Apr 29, 2010 3:25 am

Why hasn't anyone created a massive self.touch function for the player that handles EVERYTHING the player can touch?
Would this cause some sort of lag or slowdown to game play?
Would this be harder/easier to mod?
What are the gains? Disadvantages?
Good God! You shot my leg off!
User avatar
Junrall
 
Posts: 191
Joined: Mon Sep 21, 2009 12:27 am
Location: North West Oregon, USA

Postby r00k » Thu Apr 29, 2010 5:19 am

WITH GREAT POWER comes great responsibility...


Code: Select all
void() player_touch =
{
   //R00k: Optional Double Jumps
   if ((other.solid == SOLID_BSP) && (self.button2) && (!(self.style & CA_OBSERVER)))
   {
      if ((time > self.timetojump) && (time > self.timetojump2))
      {
         if ((!self.flags & FL_ONGROUND))
            self.flags = self.flags + FL_ONGROUND;
            
         self.velocity = v_up + (self.velocity * 2);
         self.velocity = v_forward + (self.velocity * 1.05);//small push when jumping
         self.velocity = v_right   + (self.velocity * 1.05);//small push when jumping
   
         self.timetojump2 = time + 0.5;
         return;
      }
   }

   if (other.classname != "player") return;

   if (other.health <= 0) return;

   if ((!other.flags & FL_ONGROUND) && (!(other.style & CA_OBSERVER)))
   {
      if (other.absmin_z >= self.absmax_z - 2)
      {
         other.flags = other.flags + FL_ONGROUND;
      }
   }
};

/*
===========
PutClientInServer

called each time a player is spawned
============
*/
void() PlayerDie;
void() PutClientInServer =
{
   local entity spot;
      
   self.classname = "player";
   
   if (self.player_flag != PF_DEAD)//dont move origin if just died
   {
      if ((mode_speedball()) && (self.killed == 0))
      {         
         if ((self.next_team.team2 == TEAM_RED))
         {            
            spot = SelectSpawnPoint ("info_player_team1");
         }
         else   
         {
            if ((self.next_team.team2 == TEAM_BLUE))
            {               
               spot = SelectSpawnPoint ("info_player_team2");
            }   
         }
      }
      else
      {
         if ((ra_map()) && ((self.player_flag == PF_PLAYING) || (ca_gametype & CA_PRACTICE_MODE)))
         {
            spot = SelectSpawnPoint ("info_teleport_destination");
         }
         else
         {
            spot = SelectSpawnPoint ("info_player_deathmatch");
         }
      }
      
      if (spot == world || spot == self.trigger_field)         
            spot = SelectSpawnPoint ("info_player_start");      

      self.trigger_field = spot;               
      self.origin = spot.origin + '0 0 10';//Some crazy reason, original spawn origins get stuck :S
      
      while (pointcontents(self.origin) == CONTENT_SOLID)//R00k: Fixes spawning in the map, caused by pre-game telefrag   [v1.62]
      {
         self.origin = self.origin + '0 0 2';
      }      
      self.angles = spot.angles;
   }
   else
   {
      self.angles_x = 0;
      self.angles_z = 0;
   }

   if (mode_speedball())
      self.touch   = player_touch;
   
   self.health          = 100;
   self.takedamage    = DAMAGE_NO;
   self.solid           = SOLID_SLIDEBOX;   
   self.movetype        = MOVETYPE_WALK;
   self.show_hostile    = 0;
   self.max_health      = 100;
   self.flags           = FL_CLIENT;
   self.dmg      = 2;         // initial water damage
   self.air_finished   = time + 12;
   self.effects        = 0;
   self.axhitme      = 0;

   if (ca_state & CA_WALL_JUMPS)
   self.touch       = player_touch;
   
   DecodeLevelParms ();
   W_SetCurrentAmmo ();
   
   self.attack_finished      = time;
   self.th_pain         = player_pain;
   self.th_die          = PlayerDie;
   self.deadflag        = DEAD_NO;
   self.fixangle       = TRUE;      // turn this way immediately
   self.velocity       = '0 0 0';
   self.avelocity       = '0 0 0';
   self.punchangle      = '0 0 0';
   self.jump_flag       = 0; // clear jump velocity to prevent falling damage
   self.think      = SUB_Null;

   setmodel(self, "progs/player.mdl");
   setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
   self.view_ofs = '0 0 22';
   
   self.flags = self.flags - (self.flags & FL_INWATER);   
   self.waterlevel = 0;
   
   player_stand1 ();   
   makevectors(self.angles);   
   
   if (intermission_running)
   {
      self.finaldest_x = time;
      self.style = (self.style | CA_CONNECTED);
      move_to_intermission (self);
      msg_entity = self;
      proto_intermission (MSG_ONE);
   }
   else
      ca_put_client_in_server();
};
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Postby Junrall » Thu Apr 29, 2010 5:43 am

:lol: Haha!
Good God! You shot my leg off!
User avatar
Junrall
 
Posts: 191
Joined: Mon Sep 21, 2009 12:27 am
Location: North West Oregon, USA

Postby Wazat » Sat May 01, 2010 8:03 pm

You mean like making the player's touch function handle touching ammo, health, triggers, grenades, spikes, lava balls, push triggers, etc?

Because then it's a major mess. Decentralizing it helps keep code clean and manageable.

Here's the thing: When I add a new object type to the game, I can simply give it a .touch, then write the function to handle how this object interacts with the player. The object knows what it does (heals the player, explodes, etc), and the player code doesn't have to have any idea. Only add code to the player if you have to or if it's significantly cleaner and more efficient, because if the player does everything then it's very hard to do anything efficiently and maintainably.

A massive player touch function would be slow (because it has to test for every case of what the touched object could be, including objects it would normally just ignore), huge and highly cluttered (because we're doing all possibilities in one place instead of separating them out into the objects themselves), and harder to add to and modify (because we have this huge function with tons of code). Perhaps one advantage is that everything touch-related would be in one place and not scattered among many files. However, that actually becomes harder when editing the item because you have to edit the code that creates and manages it (spawn function, think function etc) in a separate file from where its touch function goes.

Ultimately, separating and compartmentalizing things makes them more maintainable, cleaner, and often more efficient. And it makes them independent, so the player code knows little to nothing about them and doesn't have to be edited and updated each time we change or add an object to the game.

That's why. Of course, that hasn't stopped some mods (especially early ones) from making massive, centralized functions that try to do everything. :D
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
Wazat
 
Posts: 771
Joined: Fri Oct 15, 2004 9:50 pm
Location: Middle 'o the desert, USA

Postby Junrall » Sat May 01, 2010 9:09 pm

Yeah, after some thought on this I came to the same conclusion... pretty much it would be bloated and not easy to add to.
Considering I'm trying to clean and simplify some things, I would be going in the wrong direction with a massive player touch function!

Though, I can see some specialized uses for a player touch function... as r00k has shown above.
Good God! You shot my leg off!
User avatar
Junrall
 
Posts: 191
Joined: Mon Sep 21, 2009 12:27 am
Location: North West Oregon, USA


Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest