Actor_gump.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2000 The Exult Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 #include "Actor_gump.h"
00024 #include "actors.h"
00025 #include "gamewin.h"
00026 #include "misc_buttons.h"
00027 
00028 #ifndef ALPHA_LINUX_CXX
00029 #  include <cstdio>
00030 #endif
00031 
00032 using std::size_t;
00033 
00034 #define TWO_HANDED_BROWN_SHAPE  48
00035 #define TWO_HANDED_BROWN_FRAME  0
00036 #define TWO_FINGER_BROWN_SHAPE  48
00037 #define TWO_FINGER_BROWN_FRAME  1
00038 
00039 /*
00040  *  Statics:
00041  */
00042 
00043 short Actor_gump::diskx = 124, Actor_gump::disky = 115;
00044 short Actor_gump::heartx = 124, Actor_gump::hearty = 132;
00045 short Actor_gump::combatx = 52, Actor_gump::combaty = 103;
00046 short Actor_gump::halox = 47, Actor_gump::haloy = 110;
00047 short Actor_gump::cmodex = 48, Actor_gump::cmodey = 132;
00048 short Actor_gump::coords[24] = {
00049   114, 10,  /* head */  115, 24,  /* back */
00050   115, 37,  /* belt */  115, 55,  /* lhand */
00051   115, 71,  /* lfinger */ 114, 85,  /* legs */
00052   76, 98,   /* feet */  35, 70,   /* rfinger */
00053   37, 56,   /* rhand */ 37, 37,   /* torso */
00054   37, 24,   /* neck */  37, 11    /* ammo */
00055 };
00056 
00057 /*
00058  *  Find the index of the closest 'spot' to a mouse point.
00059  *
00060  *  Output: Index, or -1 if unsuccessful.
00061  */
00062 
00063 int Actor_gump::find_closest
00064   (
00065   int mx, int my,     // Mouse point in window.
00066   int only_empty      // Only allow empty spots.
00067   )
00068 {
00069   mx -= x; my -= y;   // Get point rel. to us.
00070   long closest_squared = 1000000; // Best distance squared.
00071   int closest = -1;   // Best index.
00072   for (size_t i = 0; i < sizeof(coords)/(2*sizeof(coords[0])); i++)
00073   {
00074     int dx = mx - spotx(i), dy = my - spoty(i);
00075     long dsquared = dx*dx + dy*dy;
00076           // Better than prev.?
00077     if (dsquared < closest_squared && (!only_empty ||
00078             !container->get_readied(i)))
00079     {
00080       closest_squared = dsquared;
00081       closest = i;
00082     }
00083   }
00084   return (closest);
00085 }
00086 
00087 /*
00088  *  Create the gump display for an actor.
00089  */
00090 
00091 Actor_gump::Actor_gump
00092   (
00093   Container_game_object *cont,  // Container it represents.  MUST
00094           //   be an Actor.
00095   int initx, int inity,     // Coords. on screen.
00096   int shnum     // Shape #.
00097   ) : Gump(cont, initx, inity, shnum)
00098 {
00099   set_object_area(Rectangle(26, 0, 104, 132), 6, 136);
00100   Actor *npc = cont->as_actor();
00101   heart_button = new Heart_button(this, heartx, hearty);
00102   if (npc->get_npc_num() == 0)
00103     disk_button = new Disk_button(this, diskx, disky);
00104   else
00105     disk_button = NULL;
00106   if (npc->get_npc_num() == 0)
00107     combat_button = new Combat_button(this, combatx, combaty);
00108   else
00109     combat_button = NULL;
00110   halo_button = new Halo_button(this, halox, haloy, npc);
00111   cmode_button = new Combat_mode_button(this, cmodex, cmodey, npc);
00112               
00113   for (size_t i = 0; i < sizeof(coords)/2*sizeof(coords[0]); i++)
00114   {     // Set object coords.
00115     Game_object *obj = container->get_readied(i);
00116     if (obj)
00117       set_to_spot(obj, i);
00118   }
00119 }
00120 
00121 /*
00122  *  Delete actor display.
00123  */
00124 
00125 Actor_gump::~Actor_gump
00126   (
00127   )
00128 {
00129   if (heart_button) delete heart_button;
00130   if (disk_button) delete disk_button;
00131   if (combat_button) delete combat_button;
00132   if (halo_button) delete halo_button;
00133   if (cmode_button) delete cmode_button;
00134 }
00135 
00136 /*
00137  *  Is a given screen point on one of our buttons?
00138  *
00139  *  Output: ->button if so.
00140  */
00141 
00142 Gump_button *Actor_gump::on_button
00143   (
00144   int mx, int my      // Point in window.
00145   )
00146 {
00147   Gump_button *btn = Gump::on_button(mx, my);
00148   if (btn)
00149     return btn;
00150   else if (heart_button && heart_button->on_button(mx, my))
00151     return heart_button;
00152   else if (disk_button && disk_button->on_button(mx, my))
00153     return disk_button;
00154   else if (combat_button && combat_button->on_button(mx, my))
00155     return combat_button;
00156   else if (halo_button && halo_button->on_button(mx, my))
00157     return halo_button;
00158   else if (cmode_button && cmode_button->on_button(mx, my))
00159     return cmode_button;
00160   return 0;
00161 }
00162 
00163 /*
00164  *  Add an object.
00165  *
00166  *  Output: 0 if cannot add it.
00167  */
00168 
00169 int Actor_gump::add
00170   (
00171   Game_object *obj,
00172   int mx, int my,     // Screen location of mouse.
00173   int sx, int sy,     // Screen location of obj's hotspot.
00174   bool dont_check,    // Skip volume check.
00175   bool combine      // True to try to combine obj.  MAY
00176           //   cause obj to be deleted.
00177   )
00178 #if 1
00179 {
00180   Game_object *cont = find_object(mx, my);
00181   
00182   if (cont && cont->add(obj, false, combine))
00183     return (1);
00184   
00185   int index = find_closest(mx, my, 1);
00186   
00187   if (index != -1 && container->add_readied(obj, index))
00188     return (1);
00189 
00190   if (container->add(obj, dont_check, combine))
00191     return (1);
00192 
00193   return (0);
00194 }
00195 #else
00196 {
00197           // Find index of closest spot.
00198   int index = find_closest(mx, my);
00199   if (!container->add_readied(obj, index))
00200   {     // Can't add it there?
00201           // Try again for an empty spot.
00202     index = find_closest(mx, my, 1);
00203     if (index < 0 || !container->add_readied(obj, index))
00204           // Just try to add it.
00205       if (!container->add(obj))
00206         return (0);
00207   }
00208           // In case it went in another obj:
00209   index = container->find_readied(obj);
00210   if (index >= 0)
00211     set_to_spot(obj, index);// Set obj. coords.
00212   return (1);
00213 }
00214 #endif
00215 
00216 /*
00217  *  Set object's coords. to given spot.
00218  */
00219 
00220 void Actor_gump::set_to_spot
00221   (
00222   Game_object *obj,
00223   int index     // Spot index.
00224   )
00225 {
00226           // Get shape info.
00227   Shape_frame *shape = obj->get_shape();
00228   if (!shape)
00229     return;     // Not much we can do.
00230   int w = shape->get_width(), h = shape->get_height();
00231           // Set object's position.
00232   obj->set_chunk(spotx(index) + shape->get_xleft() - w/2 - object_area.x,
00233     spoty(index) + shape->get_yabove() - h/2 - object_area.y);
00234           // Shift if necessary.
00235   int x0 = obj->get_cx() - shape->get_xleft(), 
00236       y0 = obj->get_cy() - shape->get_yabove();
00237   int newcx = obj->get_cx(), newcy = obj->get_cy();
00238   if (x0 < 0)
00239     newcx -= x0;
00240   if (y0 < 0)
00241     newcy -= y0;
00242   int x1 = x0 + w, y1 = y0 + h;
00243   if (x1 > object_area.w)
00244     newcx -= x1 - object_area.w;
00245   if (y1 > object_area.h)
00246     newcy -= y1 - object_area.h;
00247   obj->set_chunk(newcx, newcy);
00248 }
00249 
00250 /*
00251  *  Paint on screen.
00252  */
00253 
00254 void Actor_gump::paint
00255   (
00256   )
00257 {
00258           // Watch for any newly added objs.
00259   for (size_t i = 0; i < sizeof(coords)/2*sizeof(coords[0]); i++)
00260   {     // Set object coords.
00261     Game_object *obj = container->get_readied(i);
00262     if (obj)//&& !obj->get_cx() && !obj->get_cy())
00263       set_to_spot(obj, i);
00264   }
00265 
00266   Gump::paint();      // Paint gump & objects.
00267 
00268   // Paint over blue lines for 2 handed
00269   Actor *actor = container->as_actor();
00270   if (actor) {
00271     if (actor->is_two_fingered()) {
00272       int sx = x + 36,  // Note this is the right finger slot shifted slightly
00273         sy = y + 70;
00274       ShapeID sid(TWO_FINGER_BROWN_SHAPE, TWO_FINGER_BROWN_FRAME, SF_GUMPS_VGA);
00275       sid.paint_shape (sx,sy);
00276     }
00277     if (actor->is_two_handed()) {
00278       int sx = x + 36,  // Note this is the right hand slot shifted slightly
00279         sy = y + 55;
00280       ShapeID sid(TWO_HANDED_BROWN_SHAPE, TWO_HANDED_BROWN_FRAME, SF_GUMPS_VGA);
00281       sid.paint_shape (sx,sy);
00282     }
00283   }
00284           // Paint buttons.
00285   if (heart_button) heart_button->paint();
00286   if (disk_button) disk_button->paint();
00287   if (combat_button) combat_button->paint();
00288   if (halo_button) halo_button->paint();
00289   if (cmode_button) cmode_button->paint();
00290           // Show weight.
00291   int max_weight = container->get_max_weight();
00292   int weight = container->get_weight()/10;
00293   char text[20];
00294   snprintf(text, 20, "%d/%d", weight, max_weight);
00295   int twidth = sman->get_text_width(2, text);
00296   const int boxw = 102;
00297   sman->paint_text(2, text, x + 28 + (boxw - twidth)/2, y + 120);
00298 }
00299 
00300 Container_game_object * Actor_gump::find_actor(int mx, int my)
00301 {
00302   return container;
00303 }

Generated on Mon Jul 9 14:42:46 2007 for ExultEngine by  doxygen 1.5.1