Allow items to specify their missile animation and also allow for custom missiles
- Custom missiles are untested - Items with custom missiles export the missile graphics in the party sheet
This commit is contained in:
@@ -859,10 +859,12 @@ void place_target(location target) {
|
||||
}
|
||||
|
||||
void do_combat_cast(location target) {
|
||||
short adjust,r1,r2,targ_num,level,bonus = 1,i,item,store_sound = 0;
|
||||
short adjust,r1,r2,targ_num,level,bonus = 1,i,item;
|
||||
snd_num_t store_sound = 0;
|
||||
cCreature *cur_monst;
|
||||
bool freebie = false,ap_taken = false,cost_taken = false;
|
||||
short num_targets = 1,store_m_type = 2;
|
||||
short num_targets = 1;
|
||||
miss_num_t store_m_type = 2;
|
||||
eFieldType spray_type_array[15] = {
|
||||
FIELD_WEB,FIELD_WEB,FIELD_WEB,
|
||||
WALL_FORCE,WALL_FORCE,
|
||||
@@ -1458,7 +1460,7 @@ void load_missile() {
|
||||
|
||||
void fire_missile(location target) {
|
||||
short r1, r2, skill, dam, dam_bonus, hit_bonus, range, targ_monst, spec_dam = 0,poison_amt = 0;
|
||||
short skill_item,m_type = 0;
|
||||
short skill_item;
|
||||
cCreature *cur_monst;
|
||||
bool exploding = false;
|
||||
missile_firer = current_pc;
|
||||
@@ -1518,27 +1520,7 @@ void fire_missile(location target) {
|
||||
std::string create_line = univ.party[missile_firer].name + " fires.";
|
||||
add_string_to_buf(create_line);
|
||||
|
||||
if(overall_mode == MODE_THROWING) {
|
||||
// TODO: Store the missile in cItem directly
|
||||
switch(univ.party[missile_firer].items[ammo_inv_slot].item_level) {
|
||||
case 7:
|
||||
m_type = 10;
|
||||
break;
|
||||
case 4:
|
||||
m_type = 1;
|
||||
break;
|
||||
case 8:
|
||||
m_type = 5;
|
||||
break;
|
||||
case 9:
|
||||
m_type = 7;
|
||||
break;
|
||||
default:
|
||||
m_type = 10;
|
||||
break;
|
||||
}
|
||||
} else if(overall_mode == MODE_FIRING || overall_mode == MODE_FANCY_TARGET)
|
||||
m_type = univ.party[missile_firer].items[ammo_inv_slot].magic ? 4 : 3;
|
||||
miss_num_t m_type = univ.party[missile_firer].items[ammo_inv_slot].missile;
|
||||
run_a_missile(univ.party[missile_firer].combat_pos,target,m_type,1,(overall_mode == MODE_FIRING) ? 12 : 14,
|
||||
0,0,100);
|
||||
|
||||
@@ -2878,7 +2860,8 @@ void monst_fire_missile(short m_num,short bless,short level,location source,shor
|
||||
|
||||
//dam_type; // 0 - fire 1 - cold 2 - magic
|
||||
bool monst_breathe(cCreature *caster,location targ_space,short dam_type) {
|
||||
short level,missile_t[4] = {13,6,8,8};
|
||||
short level;
|
||||
miss_num_t missile_t[4] = {13,6,8,8};
|
||||
eDamageType type[4] = {eDamageType::FIRE, eDamageType::COLD, eDamageType::MAGIC, eDamageType::UNBLOCKABLE};
|
||||
location l;
|
||||
|
||||
@@ -4356,7 +4339,9 @@ bool combat_cast_mage_spell() {
|
||||
}
|
||||
|
||||
void combat_immed_mage_cast(short current_pc, eSpell spell_num, bool freebie) {
|
||||
short target, store_m_type = 0, i, store_sound = 0, num_opp = 0, r1;
|
||||
short target, i, num_opp = 0, r1;
|
||||
snd_num_t store_sound = 0;
|
||||
miss_num_t store_m_type = 0;
|
||||
short bonus = freebie ? 1 : stat_adj(current_pc,eSkill::INTELLIGENCE);
|
||||
cCreature* which_m;
|
||||
start_missile_anim();
|
||||
@@ -4544,7 +4529,9 @@ bool combat_cast_priest_spell() {
|
||||
}
|
||||
|
||||
void combat_immed_priest_cast(short current_pc, eSpell spell_num, bool freebie) {
|
||||
short target,i,store_sound = 0,store_m_type = 0,num_opp = 0;
|
||||
short target,i,num_opp = 0;
|
||||
snd_num_t store_sound = 0;
|
||||
miss_num_t store_m_type = 0;
|
||||
short bonus = freebie ? 1 : stat_adj(current_pc,eSkill::INTELLIGENCE);
|
||||
cCreature *which_m;
|
||||
effect_pat_type protect_pat = {{
|
||||
|
@@ -66,6 +66,7 @@ extern tessel_ref_t bw_pats[6];
|
||||
extern short combat_posing_monster , current_working_monster ; // 0-5 PC 100 + x - monster x
|
||||
extern short store_talk_face_pic;
|
||||
extern cUniverse univ;
|
||||
extern cCustomGraphics spec_scen_g;
|
||||
|
||||
// Talk vars
|
||||
extern eGameMode store_pre_talk_mode;
|
||||
@@ -91,18 +92,18 @@ extern short heal_costs[8];
|
||||
extern short terrain_there[9][9];
|
||||
|
||||
// Missile anim vars
|
||||
typedef struct {
|
||||
struct store_missile_type {
|
||||
location dest;
|
||||
short missile_type; // -1 no miss
|
||||
miss_num_t missile_type; // -1 no miss
|
||||
short path_type,x_adj,y_adj;
|
||||
} store_missile_type;
|
||||
typedef struct {
|
||||
};
|
||||
struct store_boom_type {
|
||||
location dest;
|
||||
short val_to_place,offset;
|
||||
short place_type; // 0 - on spot, 1 - random area near spot
|
||||
short boom_type; // -1 no miss
|
||||
short x_adj,y_adj;
|
||||
} store_boom_type;
|
||||
};
|
||||
store_missile_type store_missiles[30];
|
||||
store_boom_type store_booms[30];
|
||||
bool have_missile,have_boom;
|
||||
@@ -257,7 +258,7 @@ void end_missile_anim() {
|
||||
boom_anim_active = false;
|
||||
}
|
||||
|
||||
void add_missile(location dest,short missile_type,short path_type,short x_adj,short y_adj) {
|
||||
void add_missile(location dest,miss_num_t missile_type,short path_type,short x_adj,short y_adj) {
|
||||
short i;
|
||||
|
||||
if(!boom_anim_active)
|
||||
@@ -280,7 +281,7 @@ void add_missile(location dest,short missile_type,short path_type,short x_adj,sh
|
||||
}
|
||||
}
|
||||
|
||||
void run_a_missile(location from,location fire_to,short miss_type,short path,short sound_num,short x_adj,short y_adj,short len) {
|
||||
void run_a_missile(location from,location fire_to,miss_num_t miss_type,short path,short sound_num,short x_adj,short y_adj,short len) {
|
||||
// if((cartoon_happening) && (anim_step < 140))
|
||||
// return;
|
||||
start_missile_anim();
|
||||
@@ -434,11 +435,30 @@ void do_missile_anim(short num_steps,location missile_origin,short sound_num) {
|
||||
missile_place_rect[i] = temp_rect;
|
||||
|
||||
// Now put in missile
|
||||
from_rect = missile_origin_rect[i];
|
||||
if(store_missiles[i].missile_type >= 7)
|
||||
from_rect.offset(18 * (t % 8),0);
|
||||
rect_draw_some_item(missiles_gworld,from_rect,
|
||||
mainPtr,temp_rect,sf::BlendAlpha);
|
||||
if(store_missiles[i].missile_type < 1000) {
|
||||
from_rect = missile_origin_rect[i];
|
||||
if(store_missiles[i].missile_type >= 7)
|
||||
from_rect.offset(18 * (t % 8),0);
|
||||
rect_draw_some_item(missiles_gworld,from_rect, mainPtr,temp_rect,sf::BlendAlpha);
|
||||
} else {
|
||||
// Custom missile graphics
|
||||
// TODO: Test this!
|
||||
int step = missile_origin_rect[i].left / 18;
|
||||
miss_num_t base = store_missiles[i].missile_type;
|
||||
bool isParty = false;
|
||||
if(base >= 10000) {
|
||||
isParty = true;
|
||||
base -= 10000;
|
||||
} else base -= 1000;
|
||||
base += step % 4;
|
||||
sf::Texture* from_gw;
|
||||
graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(base, isParty);
|
||||
from_rect.width() = 18;
|
||||
from_rect.height() = 18;
|
||||
if(step >= 4)
|
||||
from_rect.offset(0,18);
|
||||
rect_draw_some_item(*from_gw,from_rect, mainPtr,temp_rect,sf::BlendAlpha);
|
||||
}
|
||||
}
|
||||
mainPtr.display();
|
||||
if((PSD[SDF_GAME_SPEED] == 3) || ((PSD[SDF_GAME_SPEED] == 1) && (t % 4 == 0)) ||
|
||||
|
@@ -48,10 +48,10 @@ bool try_pc_anim_move(short i,location start,short x,short y);
|
||||
void start_missile_anim();
|
||||
short get_missile_direction(location origin_point,location the_point);
|
||||
void end_missile_anim() ;
|
||||
void run_a_missile(location from,location fire_to,short miss_type,short path,short sound_num,short x_adj,short y_adj,short len);
|
||||
void run_a_missile(location from,location fire_to,miss_num_t miss_type,short path,short sound_num,short x_adj,short y_adj,short len);
|
||||
void run_a_boom(location boom_where,short type,short x_adj,short y_adj);
|
||||
void mondo_boom(location l,short type);
|
||||
void add_missile(location dest,short missile_type,short path_type,short x_adj,short y_adj);
|
||||
void add_missile(location dest,miss_num_t missile_type,short path_type,short x_adj,short y_adj);
|
||||
void add_explosion(location dest,short val_to_place,short place_type,short boom_type,short x_adj,short y_adj);
|
||||
void do_missile_anim(short num_steps,location missile_origin,short sound_num) ;
|
||||
void do_explosion_anim(short sound_num,short expand);
|
||||
|
@@ -740,6 +740,49 @@ void cItem::append(legacy::item_record_type& old){
|
||||
unsellable = old.item_properties & 16;
|
||||
reserved1 = old.reserved1;
|
||||
reserved2 = old.reserved2;
|
||||
// Set missile, if needed
|
||||
switch(variety) {
|
||||
case eItemType::ARROW:
|
||||
case eItemType::BOLTS:
|
||||
missile = magic ? 4 : 3;
|
||||
break;
|
||||
case eItemType::THROWN_MISSILE:
|
||||
// This is tricky... basically, all we can really do is guess.
|
||||
// We'll base our guess on the item's level, since the preset items have standard levels
|
||||
switch(item_level) {
|
||||
case 7: // Throwing knives
|
||||
missile = 10;
|
||||
break;
|
||||
case 4: // Darts
|
||||
missile = 1;
|
||||
break;
|
||||
case 8: // Javelins
|
||||
missile = 5;
|
||||
break;
|
||||
case 9: // Razordisks
|
||||
missile = 7;
|
||||
break;
|
||||
default:
|
||||
auto npos = std::string::npos;
|
||||
// Okay, that failed. Try examining the item's name.
|
||||
// We'll use the unidentified name since it's more likely to contain the appropriate generic words
|
||||
if(name.find("Knife") != npos) missile = 10;
|
||||
else if(name.find("Knives") != npos) missile = 10;
|
||||
else if(name.find("Spear") != npos) missile = 5;
|
||||
else if(name.find("Javelin") != npos) missile = 5;
|
||||
else if(name.find("Razordisk") != npos) missile = 7;
|
||||
else if(name.find("Star") != npos) missile = 7;
|
||||
else if(name.find("Dart") != npos) missile = 1;
|
||||
else if(name.find("Rock") != npos) missile = 12;
|
||||
// Okay, give up. Fall back to darts since we have no idea what's correct.
|
||||
else missile = 1;
|
||||
break;
|
||||
}
|
||||
case eItemType::MISSILE_NO_AMMO:
|
||||
// Just assume it's a sling and use the rock missile.
|
||||
missile = 12;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cItem::writeTo(std::ostream& file, std::string prefix) const {
|
||||
|
@@ -35,6 +35,7 @@ public:
|
||||
short value;
|
||||
unsigned int weight;
|
||||
unsigned int special_class;
|
||||
miss_num_t missile;
|
||||
location item_loc;
|
||||
std::string full_name;
|
||||
std::string name;
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#define BOE_DATA_SIMPLETYPES_H
|
||||
|
||||
typedef unsigned short mon_num_t;
|
||||
typedef signed short miss_num_t;
|
||||
typedef unsigned short ter_num_t;
|
||||
typedef signed short spec_num_t;
|
||||
typedef signed short item_num_t;
|
||||
|
@@ -881,6 +881,13 @@ void cUniverse::check_item(cItem& item) {
|
||||
check_monst(party.summons[monst - 10000]);
|
||||
else check_monst(scenario.scen_monsters[monst]);
|
||||
}
|
||||
if(item.variety == eItemType::ARROW || item.variety == eItemType::BOLTS || item.variety == eItemType::MISSILE_NO_AMMO || item.variety == eItemType::THROWN_MISSILE) {
|
||||
if(item.missile >= 10000)
|
||||
for(int i = 0; i < 4; i++)
|
||||
used_graphics.insert(item.missile - 10000 + i);
|
||||
else if(item.missile >= 1000)
|
||||
update_missiles[item.missile - 1000].insert(&item);
|
||||
}
|
||||
}
|
||||
|
||||
extern cCustomGraphics spec_scen_g;
|
||||
@@ -895,6 +902,7 @@ pic_num_t cUniverse::addGraphic(pic_num_t pic, ePicType type) {
|
||||
case PIC_MONST_LG: needSlots = 16; break;
|
||||
case PIC_ITEM: needSlots = 1; break;
|
||||
case PIC_PC: needSlots = 4; break;
|
||||
case PIC_MISSILE: needSlots = 4; break;
|
||||
default: break;
|
||||
}
|
||||
pic_num_t pos = -1;
|
||||
@@ -923,7 +931,7 @@ void cUniverse::exportGraphics() {
|
||||
// - Monster graphics for monsters summoned by custom items or captured in the party's soul crystal
|
||||
// - Item graphics for custom items that the party has in their possession or in their saved item rectangles
|
||||
// - Custom PC graphics - TODO: Rendering support for custom PC graphics
|
||||
// TODO: Missile graphics for custom items/monsters
|
||||
// TODO: Missile graphics for custom monsters
|
||||
// So basically, almost all the graphics are linked to items.
|
||||
used_graphics.clear();
|
||||
for(int i = 0; i < 6; i++) {
|
||||
@@ -960,6 +968,12 @@ void cUniverse::exportGraphics() {
|
||||
item->graphic_num = 10000 + pos;
|
||||
}
|
||||
update_items.clear();
|
||||
for(auto pic : update_missiles) {
|
||||
pic_num_t pos = addGraphic(pic.first, PIC_MISSILE);
|
||||
for(auto& item : pic.second)
|
||||
item->missile = 10000 + pos;
|
||||
}
|
||||
update_missiles.clear();
|
||||
for(auto pic : update_monsters) {
|
||||
int sz = pic.first / 1000, base = pic.first % 1000;
|
||||
ePicType type;
|
||||
|
@@ -154,7 +154,7 @@ enum eAmbientSound {
|
||||
|
||||
class cUniverse{
|
||||
template<typename T> using update_info = std::set<T*>;
|
||||
std::map<pic_num_t, update_info<cItem>> update_items;
|
||||
std::map<pic_num_t, update_info<cItem>> update_items, update_missiles;
|
||||
std::map<pic_num_t, update_info<cMonster>> update_monsters;
|
||||
std::map<pic_num_t, update_info<cPlayer>> update_pcs;
|
||||
std::set<pic_num_t> used_graphics;
|
||||
|
Reference in New Issue
Block a user