Ejemplo n.º 1
0
void Nokia1202::_flush()
{
  uint16_t i, j;

  for(i=0; i < NOKIA1202_LINES; i++) {
    if (_dirtybits[i]) {
      if (_dirtybits[i] == 0xFFFF) {
        setxy(0, i);
        digitalWrite(_csPin, LOW);
        for (j=0; j < NOKIA1202_COLUMNS; j++) {
          bulkwrite(font_5x7[_framebuffer[i * NOKIA1202_COLUMNS + j]-' '],
                    NOKIA1202_CHAR_WIDTH);
        }
        digitalWrite(_csPin, HIGH);
      } else {
        for (j=0; j < NOKIA1202_COLUMNS; j++) {
          if (_dirtybits[i] & 1 << j) {
            setxy(j * NOKIA1202_CHAR_WIDTH, i);
            _writefont(_framebuffer[i * NOKIA1202_COLUMNS + j]);
            _dirtybits[i] &= ~(1 << j);
          }
        }
      }
    }
  }
}
Ejemplo n.º 2
0
/* Fully erase DDRAM */
void Nokia1202::clear()
{
  int i;

  setxy(0, 0);
  digitalWrite(_csPin, LOW);
  for (i=0; i < NOKIA1202_COLUMNS * NOKIA1202_CHAR_WIDTH * (NOKIA1202_LINES+1); i++) {
    SPI.transfer9( 0x100 );  // Write 0
  }
  digitalWrite(_csPin, HIGH);
  _x = 0;
  _y = 0;
  setxy(0, 0);

#ifdef NOKIA1202_USE_FRAMEBUFFER
  // Clear framebuffer RAM
  for (i=0; i < NOKIA1202_COLUMNS * NOKIA1202_LINES; i++)
    _framebuffer[i] = ' ';
  // Clear dirtybits array
  for (i=0; i < NOKIA1202_LINES; i++)
    _dirtybits[i] = 0x0000;
#endif
  // Plant the cursor at its new position.
  if (_useCursor) {
#ifdef NOKIA1202_USE_FRAMEBUFFER
    _framebuffer[0] = 0x80;
#endif
    _writefont(0x80);
    setxy(0, 0);
  }

}
Ejemplo n.º 3
0
/* A .setCursor() UI function so the user can move the cursor around.
 * It has to manage the erasing/rewriting of the cursor too, if applicable.
 */
void Nokia1202::setCursor(uint8_t x, uint8_t y)
{
  if (x >= NOKIA1202_COLUMNS || y >= NOKIA1202_LINES)
    return;

  // Erase the cursor presently at _x,_y before moving it
  if (_useCursor) {
#ifdef NOKIA1202_USE_FRAMEBUFFER
    _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' ';
    _dirtybits[_y] |= 1 << _x;
#else
    _writefont(' ');
#endif
  }
  _x = x;
  _y = y;

  if (_useCursor) {
#ifdef NOKIA1202_USE_FRAMEBUFFER
    _framebuffer[_y * NOKIA1202_COLUMNS + _x] = 0x80;
    _dirtybits[_y] |= 1 << _x;
    _flush();
#else
    setxy(_x * NOKIA1202_CHAR_WIDTH, _y);
    _writefont(0x80);
#endif
  }

// Note the ifNdef here:
#ifndef NOKIA1202_USE_FRAMEBUFFER
  setxy(_x * NOKIA1202_CHAR_WIDTH, _y);
#endif
}
Ejemplo n.º 4
0
void tty_erase_screen (void)
{
#ifdef _WIN32
	CONSOLE_SCREEN_BUFFER_INFO	info;

	if (!GetConsoleScreenBufferInfo (tty_stdout, &info)) {
		printf ("tty_erase_screen: can't get Console buffer info!\r\n");
		return;
	}
	if (info.srWindow.Top + 25 > info.dwSize.Y)
		tty_start_y = info.dwSize.Y - 25;
	else
		tty_start_y = info.srWindow.Top;
	tty_start_x = 0;
	tty_max_x = 79;
	tty_max_y = info.srWindow.Bottom;
#if 0
	printf ("Cursor: X=%u, Y=%u\r\n", info.dwCursorPosition.X, info.dwCursorPosition.Y);
	printf ("Max. window size: Width=%u, Height=%u\r\n", info.dwMaximumWindowSize.X, info.dwMaximumWindowSize.Y);
	printf ("Size: Width=%u, Height=%u\r\n", info.dwSize.X, info.dwSize.Y);
	printf ("Window: Bottom=%u, Left=%u, Right=%u, Top=%u\r\n", info.srWindow.Bottom, info.srWindow.Left, info.srWindow.Right, info.srWindow.Top);
	printf ("Attributes: 0x%04x\r\n", info.wAttributes);
#endif
	setregion (tty_start_x, tty_start_y,
		   ' ', tty_attribs,
		   tty_max_x - tty_start_x + 1, tty_max_y - tty_start_y + 1);
	setxy (tty_start_x, tty_start_y);
#else
	printf ("\x1b[2J");
	tty_gotoxy (1, 1);
	fflush (stdout);
#endif
}
Ejemplo n.º 5
0
Archivo: home.c Proyecto: Greeeg/uWatch
void home_task(void)
{

	task_open();
	current_menu_item = 1;
	current_tid = 0;
	while(1)
	{
		
		if( current_tid  == 0)
		{
		clearBuff();
		
		
		setxy(2,4);
		xprint("%s\n0x%04X",mainMenu[current_menu_item].name,mainMenu[current_menu_item].task ); 
		
		lcd_xmit();
		
		}
		event_wait( buttonEvent );
		
		char button_state = button_get_pressed();
		if(current_tid == 0)
		{
			if(( button_state & BUTTON_DOWN )&&( current_menu_item > 0 ))
			{
				current_menu_item--; 
				// antmation?
			}
			else if(( button_state & BUTTON_UP )&&( current_menu_item < N_MENU -1 ))
			{
				current_menu_item++;
			}
			else if(( button_state & BUTTON_SELECT )) // no task running
			{
				// call up a new task
			
				task_create( mainMenu[current_menu_item].task, 10, 0, 0, 0 ); // should be a lower priority than this task
			
				// store tid
				current_tid = 1;//task_id_get( mainMenu[current_menu_item].task );
			
			}
		}
		else
		{ 
		if(( button_state & BUTTON_MENU ))
		{
			task_kill( mainMenu[current_menu_item].task );
			current_tid = 0;
		}
		}
		task_wait(10);
			//P2OUT ^= BIT3;
	}
	
	task_close();

}
Ejemplo n.º 6
0
void BOX::xyout(int x, int y, const string &s, COLORS b, COLORS bc) const
{
    textcolor(b);
    textbackground(bc);
    cout << setxy(left+1+x, top+y) << s;
    textcolor(color);
    textbackground(bgcolor);
}
Ejemplo n.º 7
0
void tty_restore_cursor (void)
{
#ifdef _WIN32
	setxy (tty_saved_x, tty_saved_y);
#else
	printf ("\x1b[u");
	fflush (stdout);
#endif
}
Ejemplo n.º 8
0
void BOX::textbox(const string &msg) const
{
    textcolor(color);
    textbackground(bgcolor);
    highvideo();
    draw_box();
    cout << setxy(left+2, top+1) << msg;
    normvideo();
}
Ejemplo n.º 9
0
void BOX::draw_box() const
{
    cout << setxy(left,         top) << "¢z";
    cout << setxy(left+width-2, top) << "¢{";
    cout << setxy(left,         top+height-1) << "¢|";
    cout << setxy(left+width-2, top+height-1) << "¢}";
    for(int x=left+2; x<left+width-2; x+=2)
    {
        cout << setxy(x, top) << "¢w";
        cout << setxy(x, top+height-1) << "¢w";
    }
    for(int y=top+1; y<top+height-1; ++y)
    {
        cout << setxy(left,         y) << "¢x" << string(width-4, ' ') << "¢x";
    }
    cout << setxy(left+4, top) << title;
    cout << setxy(left+width-2-footer.size(), top+height-1) << footer;
}
Ejemplo n.º 10
0
STDMETHODIMP CPDObjectSymbolInstance::Move(/*[in]*/ double dx, /*[in]*/ double dy)
{
    setxy(m_x+dx, m_y+dy);

    return S_OK;
}
Ejemplo n.º 11
0
void SWSerLCDpa::setxy(int x, int y, int n)
{
    setxy(x,y);
    print(n);
}
Ejemplo n.º 12
0
void SWSerLCDpa::setxy(int x, int y, long n, int base)
{
    setxy(x,y);
    print(n, base);
}
Ejemplo n.º 13
0
void SWSerLCDpa::setxy(int x, int y, const char *s)
{
    setxy(x,y);
    print(s);
}
Ejemplo n.º 14
0
void SWSerLCDpa::clearline(int line)
{
    setxy(0,line);
    print("?l");
    delay(20);
}
Ejemplo n.º 15
0
// death is called when an object dies (weapon destructed, etc.)
// for special effects ..
short weap::death()
{
	// Note that the 'dead' variable should ALREADY be set by the
	// time this function is called, so that we can easily reverse
	// the decision :)

	walker  *newob = NULL;

	if (death_called)  // Make sure we don't get multiple deaths
		return 0;

	death_called = 1;

	switch (family)
	{
		case FAMILY_KNIFE: // for returning knife
			if (owner && owner->query_family() != FAMILY_SOLDIER)
				break;  // only soldiers get returning knives
			newob = screenp->add_ob(ORDER_FX, FAMILY_KNIFE_BACK);
			newob->owner = owner;
			newob->center_on(this);
			newob->lastx = lastx;
			newob->lasty = lasty;
			newob->stepsize = stepsize;
			newob->ani_type = ANI_ATTACK;
			newob->damage = damage;
			break;  // end of soldier returning knife
		case FAMILY_ROCK: // used for the elf's bouncing rock, etc.
			if (!do_bounce || !lineofsight || collide_ob) // died of natural causes
				break;
			dead = 0; // first, un-dead us so we can collide ..
			// Did we hit a barrier?
			if (screenp->query_grid_passable(xpos+lastx, ypos+lasty, this))
			{
				dead = 1;
				break; // if not, die like normal
			}
			if (screenp->query_grid_passable(xpos-lastx, ypos+lasty, this))
			{
				setxy(xpos-lastx, ypos+lasty);  // bounce 'down-left'
				lastx = -lastx;
				death_called = 0;
				break;
			}
			if (screenp->query_grid_passable(xpos+lastx, ypos-lasty, this))
			{
				setxy(xpos+lastx, ypos-lasty); // bounce 'up-right'
				lasty = -lasty;
				death_called = 0;
				break;
			}
			if (screenp->query_grid_passable(xpos-lastx, ypos-lasty, this))
			{
				setxy(xpos-lastx, ypos-lasty);
				lastx = -lastx;
				lasty = -lasty;
				death_called = 0;
				break;
			}
			// Else we're really stuck, so die :)
			dead = 1;
			break;
		case FAMILY_FIRE_ARROW: // only for exploding, really
		case FAMILY_BOULDER:
			if (!skip_exit)
				break;  // skip_exit means we're supposed to explode :)
			if (!owner || owner->dead)
				owner = this;
			newob = screenp->add_ob(ORDER_FX, FAMILY_EXPLOSION, 1);
			if (!newob)
				break; // failsafe
			if (on_screen())
				screenp->soundp->play_sound(SOUND_EXPLODE);
			newob->owner = owner;
			newob->stats->hitpoints = 0;
			newob->stats->level = owner->stats->level;
			newob->ani_type = ANI_EXPLODE;
			newob->center_on(this);
			newob->damage = damage*2;
			break;  // end fire (exploding) arrows
		case FAMILY_WAVE: // grow to wave2
			dead = 0;
			transform_to(ORDER_WEAPON, FAMILY_WAVE2);
			stats->hitpoints = stats->max_hitpoints;
			break;  // end wave -> wave2
		case FAMILY_WAVE2: // grow to wave3
			dead = 0;
			transform_to(ORDER_WEAPON, FAMILY_WAVE3);
			stats->hitpoints = stats->max_hitpoints;
			break;  // end wave2 -> wave3
		case FAMILY_DOOR: // display open picture
			newob = screenp->add_weap_ob(ORDER_FX, FAMILY_DOOR_OPEN);
			if (!newob)
				break;
			newob->ani_type = ANI_DOOR_OPEN;
			newob->setxy(xpos, ypos);
			newob->stats->level = stats->level;
			newob->team_num = team_num;
			//      newob->ignore = 1;
			// What way are we 'facing'?
			if (mysmoother->query_genre_x_y((xpos/GRID_SIZE),(ypos/GRID_SIZE)-1)
			        == TYPE_WALL) // a wall above us?
			{
				newob->curdir = FACE_RIGHT;
				//        newob->setxy(xpos, ypos-12); // and move us 'up'
			}
			else
			{
				curdir = FACE_UP;
			}
			break; // end open the door ..
		default:
			break;
	}

	return 1;

}
Ejemplo n.º 16
0
// Intelligent writing & processing of a single character
size_t Nokia1202::write(uint8_t c)
{
  uint8_t i = 0;

  // Process the character as-is
  if (c > 0x82)
    c = 0x20;

  if (c >= 0x20) {
#ifdef NOKIA1202_USE_FRAMEBUFFER
    _framebuffer[_y * NOKIA1202_COLUMNS + _x] = c;
    _dirtybits[_y] |= 1 << _x;
#else
    _writefont(c);
#endif
    _x++;
  } else {
    // Process control character
    switch (c) {
      case '\n':
        if (_useCursor) {
          // Erase the cursor presently at _x,_y before moving it
#ifdef NOKIA1202_USE_FRAMEBUFFER
          _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' ';
          _dirtybits[_y] |= 1 << _x;
#else
          _writefont(' ');
#endif
        }
        _x = 0;
        _y++;
// Note the "ifNdef" in this line:
#ifndef NOKIA1202_USE_FRAMEBUFFER
        setxy(_x * NOKIA1202_CHAR_WIDTH, _y);
#endif
        break;

      case '\t':
        if (_useCursor) {
          // Erase the cursor presently at _x,_y before moving it
#ifdef NOKIA1202_USE_FRAMEBUFFER
          _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' ';
          _dirtybits[_y] |= 1 << _x;
#else
          _writefont(' ');
#endif
        }
        if (_x % _tabSpacing == 0) {
          _x += _tabSpacing;
        } else {
          _x += _x % _tabSpacing;
        }
#ifndef NOKIA1202_USE_FRAMEBUFFER
        setxy(_x * NOKIA1202_CHAR_WIDTH, _y);
#endif
        break;

      case '\b':
        if (_useCursor) {
          // Erase the cursor presently at _x,_y before moving it
#ifdef NOKIA1202_USE_FRAMEBUFFER
          _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' ';
          _dirtybits[_y] |= 1 << _x;
#else
          _writefont(' ');
#endif
        }
        if (_x > 0) {
          _x--;
#ifdef NOKIA1202_USE_FRAMEBUFFER
          _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' ';
          _dirtybits[_y] |= 1 << _x;
#else
          setxy(_x * NOKIA1202_CHAR_WIDTH, _y);
          _writefont(' ');
          setxy(_x * NOKIA1202_CHAR_WIDTH, _y);
#endif
        }
        break;
      // No default section; any other ctrl char is ignored
    }
                                
  }

  if (_x >= NOKIA1202_COLUMNS) {
    // Shift down 1 row
    _y++;
    _x = 0;
  }

  if (_y >= NOKIA1202_LINES) {
    // Ut oh, we must scroll (or roll back to the top in no-framebuffer mode)
#ifdef NOKIA1202_USE_FRAMEBUFFER
    for (i=1; i < NOKIA1202_LINES; i++) {
      // Copy line to line above
      memcpy(_framebuffer + (i-1) * NOKIA1202_COLUMNS,
             _framebuffer + i * NOKIA1202_COLUMNS,
             NOKIA1202_COLUMNS);
      _dirtybits[i-1] = 0xFFFF;
    }
    // Cursor re-set to the bottom line
    _y = NOKIA1202_LINES - 1;
    // Clear the bottom line
    memset(_framebuffer + _y * NOKIA1202_COLUMNS,
           ' ',
           NOKIA1202_COLUMNS);
    _dirtybits[_y] = 0xFFFF;
#else
    _y = 0;
#endif
  }

  // Plant the cursor at its new position.
  if (_useCursor) {
#ifdef NOKIA1202_USE_FRAMEBUFFER
    _framebuffer[_y * NOKIA1202_COLUMNS + _x] = 0x80;
    _dirtybits[_y] |= 1 << _x;
#else
    setxy(_x * NOKIA1202_CHAR_WIDTH, _y);
    _writefont(0x80);
#endif
  }

  // Commit data to screen (framebuffer mode) or set cursor position (non-framebuffer mode)
#ifdef NOKIA1202_USE_FRAMEBUFFER
  if (_doFlush)  // An optimization that makes puts() a lot faster...
    _flush();
#else
  setxy(_x * NOKIA1202_CHAR_WIDTH, _y);
#endif
	return 1;
}
Ejemplo n.º 17
0
short effect::act()
{
	short temp;
	Sint32 xd, yd, distance, generic;
	oblink *foelist, *here;
	walker *newob;
	short numfoes;

	// Make sure everyone we're poshorting to is valid
	if (foe && foe->dead)
		foe = NULL;
	if (leader && leader->dead)
		leader = NULL;
	if (owner && owner->dead)
		owner = NULL;

	collide_ob = NULL; // always start with no collison..

	// Any special actions ..
	switch (family) // determine what to do..
	{
		case FAMILY_GHOST_SCARE:
			if (owner)
				center_on(owner);
			break;
		case FAMILY_MAGIC_SHIELD: // revolve around owner
			if (!owner || owner->dead)
			{
				dead = 1;
				death();
				break;
			}
			switch (drawcycle % 16)
			{
				case 0:
					xd = 0;
					yd = -24;
					break;
				case 1:
					xd = -9;
					yd = -22;
					break;
				case 2:
					xd = -17;
					yd = -17;
					break;
				case 3:
					xd = -22;
					yd = -9;
					break;

				case 4:
					xd = -24;
					yd = 0;
					break;
				case 5:
					xd = -22;
					yd = 9;
					break;
				case 6:
					xd = -17;
					yd = 17;
					break;
				case 7:
					xd = -9;
					yd = 22;
					break;

				case 8:
					xd = 0;
					yd = 24;
					break;
				case 9:
					xd = 9;
					yd = 22;
					break;
				case 10:
					xd = 17;
					yd = 17;
					break;
				case 11:
					xd = 22;
					yd = 9;
					break;

				case 12:
					xd = 24;
					yd = 0;
					break;
				case 13:
					xd = 22;
					yd = -9;
					break;
				case 14:
					xd = 17;
					yd = -17;
					break;
				case 15:
					xd = 9;
					yd = -22;
					break;
			}
			center_on(owner);
			setxy( (short)( xpos+xd ), (short) (ypos+yd) );
			foelist = screenp->find_foe_weapons_in_range(
			              screenp->oblist, sizex, &temp, this);
			here = foelist;
			while (foelist)  // first weapons
			{
				stats->hitpoints -= foelist->ob->damage;
				foelist->ob->dead = 1;
				foelist->ob->death();
				foelist = foelist->next;
			}
			delete_list(here);
			foelist = screenp->find_foes_in_range(
			              screenp->oblist, sizex, &temp, this);
			here = foelist;
			while (foelist) // second enemies
			{
				stats->hitpoints -= foelist->ob->damage;
				attack(foelist->ob);
				dead = 0;
				foelist = foelist->next;
			}
			delete_list(here);
			if ( (stats->hitpoints <= 0) || (lifetime-- < 0) )
			{
				dead = 1;
				death();
			}
			break; // end of magic shield case
		case FAMILY_BOOMERANG: // fighter's boomerang
			// Zardus: FIX: if the drawcycle is in its >253s, the boomerang dies. This will fix the bug where
			// the boomerang comes back to 0 (owner) after spiraling around all the way if the owner has
			// that good of an ability (to keep its life so high). This caps boomerang ability, though... Another
			// fix could be to make the drawcycle var an int or at least something with more capacity than char.
			if (!owner || owner->dead || drawcycle > 253)
			{
				dead = 1;
				death();
				break;
			}
			switch (drawcycle % 16)
			{
				case 0:
					xd = 0;
					yd = -24;
					break;
				case 1:
					xd = -9;
					yd = -22;
					break;
				case 2:
					xd = -17;
					yd = -17;
					break;
				case 3:
					xd = -22;
					yd = -9;
					break;

				case 4:
					xd = -24;
					yd = 0;
					break;
				case 5:
					xd = -22;
					yd = 9;
					break;
				case 6:
					xd = -17;
					yd = 17;
					break;
				case 7:
					xd = -9;
					yd = 22;
					break;

				case 8:
					xd = 0;
					yd = 24;
					break;
				case 9:
					xd = 9;
					yd = 22;
					break;
				case 10:
					xd = 17;
					yd = 17;
					break;
				case 11:
					xd = 22;
					yd = 9;
					break;

				case 12:
					xd = 24;
					yd = 0;
					break;
				case 13:
					xd = 22;
					yd = -9;
					break;
				case 14:
					xd = 17;
					yd = -17;
					break;
				case 15:
					xd = 9;
					yd = -22;
					break;
			}
			xd *= (drawcycle+4);
			xd /= 48;
			yd *= (drawcycle+4);
			yd /= 48;
			center_on(owner);
			setxy((short) (xpos+xd), (short) (ypos+yd) );
			foelist = screenp->find_foe_weapons_in_range(
			              screenp->oblist, sizex*2, &temp, this);
			here = foelist;
			while (foelist)  // first weapons
			{
				stats->hitpoints -= foelist->ob->damage;
				foelist->ob->dead = 1;
				foelist->ob->death();
				foelist = foelist->next;
			}
			delete_list(here);
			foelist = screenp->find_foes_in_range(
			              screenp->oblist, sizex, &temp, this);
			here = foelist;
			while (foelist) // second enemies
			{
				stats->hitpoints -= foelist->ob->damage;
				attack(foelist->ob);
				dead = 0;
				foelist = foelist->next;
			}
			delete_list(here);
			if ( (stats->hitpoints <= 0) || (lifetime-- < 0) )
			{
				dead = 1;
				death();
			}
			break; // end of boomerang case
		case FAMILY_KNIFE_BACK: // returning blade
			if (!owner || owner->dead)
			{
				dead = 1;
				break;
			}
			distance = distance_to_ob(owner);
			if (distance > 10)
			{
				xd = yd = 0; // zero out distance movements
				if (owner->xpos > xpos)
				{
					if ( (owner->xpos - xpos) > stepsize )
						xd = stepsize;
					else
						xd = owner->xpos - xpos;
				}
				else if (owner->xpos < xpos)
				{
					if ( (xpos - owner->xpos) > stepsize )
						xd = -stepsize;
					else
						xd = owner->xpos - xpos;
				}
				if (owner->ypos > ypos)
				{
					if ( (owner->ypos - ypos) > stepsize )
						yd = stepsize;
					else
						yd = owner->ypos - ypos;
				}
				else if (owner->ypos < ypos)
				{
					if ( (ypos - owner->ypos) > stepsize )
						yd = -stepsize;
					else
						yd = owner->ypos - ypos;
				}
				setxy((short) (xpos+xd), (short) (ypos+yd) );
				newob = screenp->add_ob(ORDER_WEAPON, FAMILY_KNIFE);
				newob->damage = damage;
				newob->owner = owner;
				newob->team_num = team_num;
				newob->death_called = 1; // to ensure no spawning of more ..
				newob->setxy(xpos, ypos);
				if (!screenp->query_object_passable((short) (xpos+xd), (short) (ypos+yd), newob))
				{
					newob->attack(newob->collide_ob);
					damage /= 4;
					//setxy(xpos-(2*xd)+random(xd), ypos-(2*yd)+random(yd));
				}
				newob->dead = 1;
			}
			else
			{
				owner->weapons_left++;
				//if (owner->user != -1)
				//{
				//  sprintf(message, "Knives now %d", owner->weapons_left);
				//  screenp->do_notify(message, owner);
				//}
				ani_type = ANI_WALK;
				dead = 1;
			}
			break;
		case FAMILY_CLOUD: // poison cloud
			if (lifetime > 0)
				lifetime--;
			else
			{
				dead = 1;
				death();
			}
			if (lifetime < 8)
				invisibility_left +=3;
			if (invisibility_left > 0)
				invisibility_left--;
			// Hit any nearby foes (not friends, for now)
			foelist = screenp->find_foes_in_range(
			              screenp->oblist, sizex, &temp, this);
			here = foelist;
			while (foelist) //
			{
				if (hits(xpos, ypos, sizex, sizey, // this is the cloud
				         foelist->ob->xpos, foelist->ob->ypos,
				         foelist->ob->sizex, foelist->ob->sizey)
				   )
				{
					attack(foelist->ob);
				} // end of actual hit
				foelist = foelist->next;
			}
			delete_list(here);
			// Are we performing some action?
			if (stats->commandlist)
				temp = stats->do_command();
			else
			{
				xd = yd = 0;
				while (xd == 0 && yd == 0)
				{
					xd = random(3)-1;
					yd = random(3)-1;
				}
				stats->add_command(COMMAND_WALK, (short) random(20), (short) xd, (short) yd);
			}
			break; // end of cloud
		case FAMILY_CHAIN: // chain lightning ..
			if (!leader || lineofsight<1 || !owner) // lost our leader, etc.? kill us ..
			{
				dead = 1;
				death();
				return 1;
			}
			// Are we at our leader? If so, attack him :)
			if (hits(xpos, ypos, sizex, sizey,
			         leader->xpos, leader->ypos, leader->sizex, leader->sizey))
			{
				// Do things ..
				newob = screenp->add_ob(ORDER_FX, FAMILY_EXPLOSION);
				if (!newob)
				{
					dead = 1;
					death();
					return 1; // failsafe
				}
				newob->owner = owner;
				newob->team_num = team_num;
				newob->stats->level = stats->level;
				newob->damage = damage;
				newob->ani_type = ANI_EXPLODE;
				newob->center_on(this);
				leader->skip_exit += 3; // can't hit us for 3 rounds ..
				if (on_screen())
					screenp->soundp->play_sound(SOUND_EXPLODE);
				// Now make new objects to seek out foes ..
				// First, are our offspring powerful enough at 1/2 our power?
				generic = (damage)/2;
				if (owner->myguy)
					foelist = screenp->find_foes_in_range(screenp->oblist,
					                                      240+(owner->myguy->intelligence/2), &temp, this);
				else
					foelist = screenp->find_foes_in_range(screenp->oblist,
					                                      240+stats->level*5, &temp, this);
				if (temp && generic>20) // more foes to find ..
				{
					here = foelist;
					numfoes = random(owner->stats->level)+1;
					while (here && numfoes--)
					{
						if (here->ob != leader && here->ob->skip_exit<1) // don't hit current guy, etc.
						{
							newob = screenp->add_ob(ORDER_FX, FAMILY_CHAIN);
							if (!newob)
							{
								delete_list(foelist);
								return 0; // failsafe
							}
							newob->owner = owner;  // our caster
							newob->leader = here->ob; // guy to attack
							newob->stats->level = stats->level;
							newob->stats->set_bit_flags(BIT_MAGICAL, 1);
							newob->damage = generic;
							newob->team_num = team_num;
							newob->center_on(this);
						} // end of wasn't current guy case
						here = here->next;
					} // end of loop for nearby foes we found
				} // end of check for nearby foes

				// Clean up our list .. ?
				// Zardus: TAG: nah, lets use delete_list
				/*here = foelist->next;
				while (here)
				{
					delete foelist;
					foelist = here;
					here = here->next;
				}
				delete foelist;*/
				delete_list(foelist);
				dead = 1;
				death();
				return 1;
			}
			// Move toward our leader ..
			lineofsight--;
			distance = distance_to_ob_center(leader);
			if (distance > stepsize*2)
			{
				xd = yd = 0; // zero out distance movements
				if (leader->xpos > xpos)
				{
					if ( (leader->xpos - xpos) > stepsize )
						xd = stepsize;
					else
						xd = leader->xpos - xpos;
				}
				else if (leader->xpos < xpos)
				{
					if ( (xpos - leader->xpos) > stepsize )
						xd = -stepsize;
					else
						xd = leader->xpos - xpos;
				}
				if (leader->ypos > ypos)
				{
					if ( (leader->ypos - ypos) > stepsize )
						yd = stepsize;
					else
						yd = leader->ypos - ypos;
				}
				else if (leader->ypos < ypos)
				{
					if ( (ypos - leader->ypos) > stepsize )
						yd = -stepsize;
					else
						yd = leader->ypos - ypos;
				}
				// Set our facing?
				curdir = facing(xd, yd);
				set_frame(ani[curdir][0]);
			} // end of big step
			else
			{
				//xd = leader->xpos;
				//yd = leader->ypos;
				center_on(leader);
				return 1;
			}
			setxy((short) (xpos+xd), (short) (ypos+yd) );
			return 1;  // so as not to animate, etc.
			//break; // end of FAMILY_CHAIN

		case FAMILY_DOOR_OPEN:

			// Here is how doors work.  They start out as a FAMILY_DOOR
			//  from ORDER_WEAPON under the weaplist.  When the door is
			//  collided with, the obmap marks the door as dead, and spawns
			//  the FAMILY_DOOR_OPEN on the weaplist (this object).  It
			//  animates ANI_DOOR_OPEN, and when it is done, it dies and
			//  spawns a FAMILY_DOOR_OPEN on the fxlist.  The amusing part
			//  is that now that it is on the fxlist, it won't act anymore,
			//  thus preventing it from continuously respawning itself.

			if (ani_type != ANI_WALK)
				return animate();
			newob = screenp->add_fx_ob(ORDER_FX, FAMILY_DOOR_OPEN);
			if (!newob)
				break;
			newob->ani_type = ANI_WALK;
			newob->setxy(xpos, ypos);
			newob->stats->level = stats->level;
			newob->team_num = team_num;
			newob->ignore = 1;
			newob->curdir = curdir;
			// set correct frame
			newob->animate();
			dead = 1;
			death();
			return 1;
			break;

		default:
			break;
	}

	// Complete previous animations (like firing)
	if (ani_type != ANI_WALK)
		return animate();

	switch (family) // determine what to do..
	{
		default:
			dead = 1;
			death();
			break;
	}

	return 0;
}