void do_elbow(void) { OBJECT *obj=current_proc->pa8; init_special(obj); if (ochar_elbow_animations[obj->ochar] & 0x80) current_proc->pa9=get_char_ani(ANIM_TABLE2,ochar_elbow_animations[obj->ochar] & 0x7f); else current_proc->pa9=get_char_ani(ANIM_TABLE1,ochar_elbow_animations[obj->ochar] & 0x7f); if (striker(SI_STRIKER_NORMAL,1,ACT_ELBOW,0xffff,5,0xf)==SYSTEM_CARRY_SET) { if (ochar_elbow_combos[obj->ochar]!=NULL && (!f_no_combos)) { process_combo_table(ochar_elbow_combos[obj->ochar]); } else { /* elbow4 */ current_proc->pdata.p_action=ACT_ELBOW_SD; process_sleep(10); } } /* elbow5 */ retract_strike_act(ACT_ELBOW_SD,3); return; }
int spc_exec_special (const char *buffer, int32_t size, double x_user, double y_user, double mag) { int error = -1; int i, found; struct spc_env spe; struct spc_arg args; struct spc_handler special; if (verbose > 3) { dump(buffer, buffer + size); } init_special(&special, &spe, &args, buffer, size, x_user, y_user, mag); for (i = 0; known_specials[i].key != NULL; i++) { found = known_specials[i].check_func(buffer, size); if (found) { error = known_specials[i].setup_func(&special, &spe, &args); if (!error) { error = special.exec(&spe, &args); } if (error) { print_error(known_specials[i].key, &spe, &args); } break; } } check_garbage(&args); return error; }
/****************************************************************************** Function: void do_knee(void) By: David Schwartz Date: Nov 1994 Parameters: None Returns: None Description: perform a knee kick ******************************************************************************/ void do_knee(void) { WORD result; OBJECT *obj=current_proc->pa8; init_special(obj); result=striker(SI_STRIKER_NORMAL,1,ACT_KNEE,ANIM_KNEE,1,0xe); if (ochar_knee_combos[obj->ochar] != NULL && (!f_no_combos)) process_combo_table(ochar_knee_combos[obj->ochar]); /* knee4 */ current_proc->pdata.p_action=ACT_KNEE_SD; if (result==SYSTEM_CARRY_SET) process_sleep(15); retract_strike(6); return; }
/* Check if the ball collides with some block (and handle that) */ static void block_ball_collide(game_t *p_game, ball_t *p_ball) { sint16_t x = (p_ball->x+BALL_WIDTH/2)/BLOCK_WIDTH; sint16_t y = (p_ball->y+BALL_HEIGHT/2)/BLOCK_HEIGHT; sint16_t rest_x = (p_ball->x+BALL_WIDTH/2)%BLOCK_WIDTH; block_t *p_block; /* Off field - ignore! */ if (y > FIELD_HEIGHT-1 || x < 0 || x > FIELD_WIDTH-1) return; p_block = &p_game->p_field[y*FIELD_WIDTH+x]; /* If the block is not empty -> collision */ if (p_block->type != TYPE_EMPTY) { int block_above = (y>0)?(p_block-FIELD_WIDTH)->type:FALSE; int block_below = (y<FIELD_HEIGHT)?(p_block+FIELD_WIDTH)->type:FALSE; int block_left = (x>0)?(p_block-1)->type:FALSE; int block_right = (x<FIELD_WIDTH)?(p_block+1)->type:FALSE; int other_vertical_block = (p_ball->y-(y*BLOCK_HEIGHT) > BLOCK_HEIGHT/2)?block_below:block_above; int other_horizontal_block = (p_ball->x-(x*BLOCK_WIDTH) > BLOCK_WIDTH/2)?block_left:block_right; /* We save space above by using (p_block-1) instead of p_game->p_field[y*FIELD_WIDTH+(x-1)] etc */ /* Lower the number of hits the field can take */ if (--p_block->hits == 0) { /* Remove block */ p_game->nr_blocks--; if (p_block->type & TYPE_SPECIAL && p_game->free_special != -1) { init_special(&p_game->p_specials[p_game->free_special], x*BLOCK_WIDTH, y*BLOCK_HEIGHT, p_block->special); DEBUG(printf("Special %d\n", p_game->p_specials[p_game->free_special].type)); } init_block(p_block, TYPE_EMPTY); /* For the "destroyer", invert the speed if the block is removed (it will be inverted once more afterwards, causing it to just keep on.) */ if (p_ball->state & BALL_STATE_DESTROYER) { draw_block(p_block, x, y); p_ball->state--; /* This implements a timeout for the destroyer (max number of blocks) */ return; } } /* Check if the ball is bouncing against the short side of the block or the long side * Since we're here we know that the ball is within the block borders, so there are two * possible cases (and two subcases): * * 1: \ ____ ____ / Here, the ball strikes a block which has a neighbor * o|____| or |____|o It should then bounce off x-wise * / |____| |____| \ * OR * 2: \ ____ ____ / Here, the ball strikes a single block, in which case it * o|____| or |____|o should bounce off if it is within the block y-borders * / \ * ____ ____ * 3: |____|____| This illustrates a case where the ball shouldn't bounce * o to the right regardless of if case 2 is true * / \ * * Alas, this does not work perfect. Perhaps a lookup-table instead? */ if (((p_ball->lastx < p_ball->x && p_ball->x+BALL_WIDTH/2 < x*BLOCK_WIDTH+3) || (p_ball->lastx > p_ball->x && p_ball->x+BALL_WIDTH/2 > (x+1)*BLOCK_WIDTH-3)) && (other_vertical_block || /* Another block above or below exists (case 1) */ (p_ball->y+BALL_HEIGHT/2 > y*BLOCK_HEIGHT && /* Case 2 */ p_ball->y+BALL_HEIGHT/2 < (y+1)*BLOCK_HEIGHT && !other_horizontal_block))) /* Case 3 */ { /* Short side - change x */ p_ball->dx = -p_ball->dx; } else { /* Long side - change y. * * Three cases: * 1: ____ 2: ____ 3: ____ * |____| |____| |____| * /| /\ /`o * o o * * Plus three corresponding cases where the ball is * travelling from right to left. The same is valid if the * ball comes from above. * * If the ball hits the first third of the block, case 1 * applies. For the last third, case 3 applies and otherwise * case 2. */ /* Ball is travelling to the right */ if (rest_x < (BLOCK_WIDTH/3)+BALL_WIDTH/2) { /* Case 1, one-way dy */ p_ball->type = BALL_TYPE_ONE_WAY; p_ball->swap = 1; /* dy instead of dx */ p_ball->dy = -p_ball->dy; p_ball->dx = (p_ball->dx > 0) ? 0 : -1; DEBUG(printf("Case 1\n")); } else if (rest_x > 2*(BLOCK_WIDTH/3)-BALL_WIDTH/2) { /* Case 3, fast dx */ p_ball->type = BALL_TYPE_FAST; p_ball->swap = 0; /* Don't swap */ p_ball->dy = -p_ball->dy; p_ball->dx += (p_ball->dx == 0) ? 1 : 0; DEBUG(printf("Case 3\n")); } else /* Case 2, just bounce */ { p_ball->dy = -p_ball->dy; p_ball->swap = 0; /* Don't swap */ DEBUG(printf("Case 2\n")); } } /* Always draw the block if it's hit (in order to have it look nicer and to remove it) */ draw_block(p_block, x, y); } }
/****************************************************************************** Function: void do_friendship(void) By: David Schwartz Date: May 1995 Parameters: None Returns: None Description: perform fighter friendship ******************************************************************************/ void do_friendship(void) { friendship_start_pause(); init_special(current_proc->pa8); ochar_friends[(current_proc->pa8)->ochar](); }