//--------- Begin of function BulletProgram::init ---------// // // <char> parentType - the type of object emits the bullet // <short> parentRecno - the recno of the object // <short> targetXLoc - the x loc of the target // <short> targetYLoc - the y loc of the target // <char> targetMobileType - target mobile type // void BulletProgram::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType) { Bullet::init(parentType, parentRecno, targetXLoc, targetYLoc, targetMobileType); cur_step = 0; BaseObj *baseObjPtr = base_obj_array[parent_base_obj_recno]; Unit *parentUnit; // for fixed total_step of bullet, set sprite.dbf's speed // // else total_step = distance to target / unitattk.dbf's bullet_speed // // start animation bullet_running die_animation // delay_step total_step // // bullet_delay in if sprite.dbf's no. of frame filled // sprite.dbf & speed > 0, take in sframe.dbf // unitattk.dbf it else use // distance to // calculate if (sprite_info->speed > 0) total_step = sprite_info->speed; if( (parentUnit = baseObjPtr->cast_to_Unit()) ) { // delay obtained from unitattk.dbf // AttackInfo* attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack; delay_step = attackInfo->bullet_delay; } else { // delay obtained from sprite.dbf if the attacker is not a unit // delay_step = sprite_info->bullet_delay; } }
//--------- Begin of function Sprite::process_die --------// // // return : <int> 1 - dying animation completes. // 0 - still dying // int Sprite::process_die() { //--------- next frame ---------// // if( sys.frame_count%2 == 0 ) // { if (cur_frame == 1) { BaseObj *baseObj = base_obj_array[base_obj_recno]; Unit* unitPtr = baseObj->cast_to_Unit(); if (unitPtr) unitPtr->add_die_effect(); } se_res.sound(cur_x_loc(), cur_y_loc(), cur_frame, 'S',sprite_id,"DIE"); if( ++cur_frame > sprite_info->die.frame_count ) return 1; // } return 0; }
//--------- Begin of function UnitOrder::set ---------// // void UnitOrder::set(int newMode, int newPara, int newXLoc, int newYLoc) { mode = newMode; para = newPara; loc_x = newXLoc; loc_y = newYLoc; ai_action_id = 0; name_id = 0; //--- set name_id to Unit::name_id if the order is attacking a unit. This is for verifying attack target ---// if( mode==UNIT_ATTACK ) { BaseObj* targetObj = base_obj_array[para]; if( targetObj->obj_type == OBJ_UNIT ) name_id = targetObj->cast_to_Unit()->name_id; } }
// --------- begin of function BulletHoming::init --------// void BulletHoming::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType) { Bullet::init(parentType, parentRecno, targetXLoc, targetYLoc, targetMobileType); // ------- find the maximum range --------// BaseObj *baseObjPtr = base_obj_array[parent_base_obj_recno]; if( baseObjPtr->cast_to_Unit() ) { Unit *parentUnit = base_obj_array[parent_base_obj_recno]->cast_to_Unit(); AttackInfo* attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack; speed = attackInfo->bullet_speed; max_step = char((attackInfo->attack_range * LOCATE_WIDTH + speed-1)/ speed); } else if( baseObjPtr->cast_to_Firm() && baseObjPtr->cast_to_Firm()->cast_to_FirmFort() ) { FirmFort *firmFort = baseObjPtr->cast_to_Firm()->cast_to_FirmFort(); speed = firmFort->bullet_speed(); max_step = 100; // unlimited range } else { err_here(); } //--------- keep backup of centre of the bullet ---------// SpriteFrame *spriteFrame = cur_sprite_frame(); // origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap // origin_x += spriteFrame->offset_x + spriteFrame->width/2; origin_y += spriteFrame->offset_y + spriteFrame->height/2; origin2_x = origin_x; origin2_y = origin_y; go_x += spriteFrame->offset_x + spriteFrame->width/2; go_y += spriteFrame->offset_y + spriteFrame->height/2; // ------- find the target_type and target_recno ------// Location *locPtr = world.get_loc(targetXLoc, targetYLoc); target_base_obj_recno = locPtr->base_obj_recno(targetMobileType); }
// --------- begin of function BulletHoming::process_move --------// void BulletHoming::process_move() { int actualStep = total_step; if( base_obj_array.is_deleted(target_base_obj_recno) ) { target_base_obj_recno = 0; } else { BaseObj *baseObj = base_obj_array[target_base_obj_recno]; Unit *unitPtr = baseObj->cast_to_Unit(); if( unitPtr && unitPtr->is_visible() ) { // ---- calculate new target_x_loc, target_y_loc -----// target_x_loc = unitPtr->next_x_loc(); target_y_loc = unitPtr->next_y_loc(); // ---- re-calculate go_x, go_y ------// // go_x/y and origin2_x/y are pointing at the centre of the bullet bitmap // it is different from Bullet go_x = unitPtr->cur_x + LOCATE_WIDTH / 2; go_y = unitPtr->cur_y + LOCATE_HEIGHT /2; //---------- set bullet movement steps -----------// SpriteFrame *spriteFrame = cur_sprite_frame(); int adjX = spriteFrame->offset_x+spriteFrame->width/2; int adjY = spriteFrame->offset_y+spriteFrame->height/2; int xStep = abs(go_x - (cur_x+adjX))/speed; int yStep = abs(go_y - (cur_y+adjY))/speed; total_step = cur_step + MAX(xStep, yStep); // a homing bullet has a limited range, if the target go outside the // the limit, the bullet can't attack the target // in this case, actualStep is the number step from the source // to the target; total_step is the max_step // otherwise, actualStep is as same as total_step actualStep = total_step; if( total_step > max_step ) { total_step = max_step; // target_x_loc and target_y_loc is limited also target_x_loc = (cur_x + adjX) + (int)(go_x-(cur_x+adjX)) / (actualStep - total_step) / LOCATE_WIDTH; target_x_loc = (cur_y + adjY) + (int)(go_y-(cur_y+adjY)) / (actualStep - total_step) / LOCATE_HEIGHT; } } } // origin2_x = origin_x; // origin2_y = origin_y; // origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap // SpriteFrame *spriteFrame = cur_sprite_frame(); short adjX = spriteFrame->offset_x + spriteFrame->width/2; short adjY = spriteFrame->offset_y + spriteFrame->height/2; origin_x = cur_x + adjX; origin_y = cur_y + adjY; cur_x = origin_x + (int)(go_x-origin_x) / (actualStep + 1 - cur_step); cur_y = origin_y + (int)(go_y-origin_y) / (actualStep + 1 - cur_step); // cur_x, cur_y is temporary pointing at the centre of bullet bitmap // detect changing direction if( cur_step > 3 ) // not allow changing direction so fast set_dir(origin2_x, origin2_y, cur_x, cur_y); // change cur_x, cur_y to bitmap reference point spriteFrame= cur_sprite_frame(); adjX = spriteFrame->offset_x + spriteFrame->width/2; adjY = spriteFrame->offset_y + spriteFrame->height/2; cur_x -= adjX; cur_y -= adjY; cur_step++; //------- update frame id. --------// if( ++cur_frame > cur_sprite_move()->frame_count ) cur_frame = 1; //----- if the sprite has reach the destintion ----// if( cur_step > total_step ) { check_hit(); cur_action = SPRITE_DIE; // Explosion // ###### begin Gilbert 17/5 ########// // if it has die frame, adjust cur_x, cur_y to be align with the target_x_loc, target_y_loc if( sprite_info->die.first_frame_recno ) { next_x = cur_x = target_x_loc * LOCATE_WIDTH; next_y = cur_y = target_y_loc * LOCATE_HEIGHT; } // ###### end Gilbert 17/5 ########// cur_frame = 1; } // change of total_step may not call warn_target, so call more warn_target else if( total_step - cur_step <= 1 ) { warn_target(); } }