Add support for custom explosions with custom sound choice

This commit is contained in:
2015-06-04 18:47:01 -04:00
parent 6c5e2b5118
commit 5bcf220204
12 changed files with 75 additions and 30 deletions

View File

@@ -129,6 +129,11 @@ same slot as the opposite direction, but aligned to the left and bottom. Add 100
slot the north and south graphics are in, and put that number in the text field where a
missile graphic is requested.</p>
<p><b>Explosion - </b>You can play custom explosion animations using the Do Sfx Burst
special node type. An explosion animation consists of 8 full-sized frames with transparent
backgrounds, which must be present in order in the graphics sheet. Add 1000 to the slot of the first frame, and put that number in the text field where the explosion type is
required.</p>
<p><b>Terrain Map Icons - </b>A terrain map icon is 12x12 pixels, and each slot on the
custom graphic sheet can hold six of them. Within a single slot, the terrain map icons are
numbered 1 through 6, from left to right, top to bottom. Multiply that number by 1000,

View File

@@ -1409,9 +1409,12 @@ has no other affect.
<dl>
<dt>Extra 1a, Extra 1b:</dt><dd>The x and y coordinates of the space for the explosion to
appear on.</dd>
<dt>Extra 2a:</dt><dd>The type of explosion. 0 - fire 1 -
teleportation 2 - electricity (blue) 3 - electricity (yellow)</dd>
<dt>Extra 2b:</dt><dd>If left at 0, the burst is a simple explosion. If set to 1, a larger burst is used for an even flashier effect.</dd>
<dt>Extra 2a:</dt><dd>The type of explosion. 0 - fire 1 - teleportation
2 - electricity (blue) 3 - electricity (yellow)</dd>
<dt>Extra 2b:</dt><dd>If left at 0, the burst is a simple explosion. If set to 1, a larger
burst is used for an even flashier effect.</dd>
<dt>Extra 2c:</dt><dd>Specifies the sound to play with the explosion. Leave at -1 to use
the default for the explosion type. (For custom explosions, the default is none.)</dd>
<dt>Note:</dt><dd>This does nothing if called when in talking mode.</dd></dd>
<dt>Type 180: Make Wandering Monster</dt><dd>A group of wandering monsters appears (at one

View File

@@ -211,7 +211,7 @@
<text top='228' left='372' width='140' height='16'>Large Dialog Icon (72x72)</text>
<text top='243' left='372' width='140' height='16'>Talk Portrait (32x32 split)</text>
<text top='258' left='372' width='140' height='16'>Item</text>
<text top='273' left='372' width='140' height='16'>Boom (currently unused)</text>
<text top='273' left='372' width='140' height='16'>Boom</text>
<text top='288' left='372' width='140' height='16'>Missile</text>
<text top='303' left='372' width='140' height='16'>Part of another graphic</text>
<text top='326' left='20' width='500' height='140'>

View File

@@ -153,9 +153,9 @@ Unused
X coordinate of space
Y coordinate of space
Unused
0 - fire, 1 - elec., 2 - telep.
Type of explosion
0 - normal, 1 - huge
Unused
Sound to play (-1 = default)
Special to Jump To
--------------------
Make Wandering Monster

View File

@@ -285,7 +285,7 @@ void run_a_missile(location from,location fire_to,miss_num_t miss_type,short pat
end_missile_anim();
}
void run_a_boom(location boom_where,short type,short x_adj,short y_adj) {
void run_a_boom(location boom_where,short type,short x_adj,short y_adj,short snd) {
// if((cartoon_happening) && (anim_step < 140))
// return;
@@ -293,17 +293,17 @@ void run_a_boom(location boom_where,short type,short x_adj,short y_adj) {
return;
start_missile_anim();
add_explosion(boom_where,-1,0,type, x_adj, y_adj);
do_explosion_anim(5,0);
do_explosion_anim(5,0,snd);
end_missile_anim();
}
void mondo_boom(location l,short type) {
void mondo_boom(location l,short type,short snd) {
short i;
start_missile_anim();
for(i = 0; i < 12; i++)
add_explosion(l,-1,1,type,0,0);
do_explosion_anim(5,0);
do_explosion_anim(5,0,snd);
end_missile_anim();
}
@@ -509,7 +509,7 @@ short get_missile_direction(location origin_point,location the_point) {
// sound_num currently ignored
// special_draw - 0 normal 1 - first half 2 - second half
void do_explosion_anim(short /*sound_num*/,short special_draw) {
void do_explosion_anim(short /*sound_num*/,short special_draw, short snd) {
rectangle active_area_rect,to_rect,from_rect;
rectangle base_rect = {0,0,36,28},text_rect;
short i,temp_val,temp_val2;
@@ -572,8 +572,12 @@ void do_explosion_anim(short /*sound_num*/,short special_draw) {
else if(special_draw < 2)
explode_place_rect[i] = rectangle();
if(special_draw < 2)
play_sound(-1 * boom_type_sound[cur_boom_type]);
if(special_draw < 2) {
snd_num_t snd_num = snd;
if(snd == -1 && cur_boom_type < 4)
snd_num = boom_type_sound[cur_boom_type];
play_sound(-1 * snd_num);
}
// Now, at last, do explosion
for(t = (special_draw == 2) ? 6 : 0; t < ((special_draw == 1) ? 6 : 11); t++) { // t goes up to 10 to make sure screen gets cleaned up
@@ -583,10 +587,15 @@ void do_explosion_anim(short /*sound_num*/,short special_draw) {
for(i = 0; i < 30; i++)
if(store_booms[i].boom_type >= 0) {
if((t + store_booms[i].offset >= 0) && (t + store_booms[i].offset <= 7)) {
from_rect = base_rect;
from_rect.offset(28 * (t + store_booms[i].offset),36 * (1 + store_booms[i].boom_type));
rect_draw_some_item(boom_gworld,from_rect,
mainPtr,explode_place_rect[i],sf::BlendAlpha);
if(cur_boom_type >= 1000) {
sf::Texture* src_gworld;
graf_pos_ref(src_gworld, from_rect) = spec_scen_g.find_graphic(cur_boom_type - 1000 + t);
rect_draw_some_item(*src_gworld, from_rect, mainPtr, explode_place_rect[i], sf::BlendAlpha);
} else {
from_rect = base_rect;
from_rect.offset(28 * (t + store_booms[i].offset),36 * (1 + store_booms[i].boom_type));
rect_draw_some_item(boom_gworld,from_rect,mainPtr,explode_place_rect[i],sf::BlendAlpha);
}
if(store_booms[i].val_to_place > 0) {
text_rect = explode_place_rect[i];

View File

@@ -49,12 +49,12 @@ 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,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 run_a_boom(location boom_where,short type,short x_adj,short y_adj,short snd = -1);
void mondo_boom(location l,short type,short snd = -1);
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);
void do_explosion_anim(short sound_num,short expand,short snd = -1);
void click_shop_rect(rectangle area_rect);
void draw_shop_graphics(bool pressed,rectangle clip_area_rect);
void refresh_shopping();

View File

@@ -3798,8 +3798,8 @@ void townmode_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
if(which_mode == eSpecCtx::TALK)
break;
if(spec.ex2b == 1)
mondo_boom(l,spec.ex2a);
else run_a_boom(l,spec.ex2a,0,0);
mondo_boom(l,spec.ex2a,spec.ex2c);
else run_a_boom(l,spec.ex2a,0,0,spec.ex2c);
break;
case eSpecType::TOWN_CREATE_WANDERING:
create_wand_monst();

View File

@@ -458,7 +458,7 @@ static const char*const button_dict[7][11] = {
" }} ", // ex1c
"@ 7 ! c T T i FD ", // ex2a
" DD / ^ ", // ex2b
" x x : : ", // ex2c
" x x x : : ", // ex2c
}, { // rectangle nodes
"mmmmmmmmm", // msg1
" ", // msg2

View File

@@ -49,6 +49,7 @@ void cPict::init(){
drawPict()[PIC_CUSTOM_ITEM] = &cPict::drawCustomItem;
drawPict()[PIC_CUSTOM_TINY_ITEM] = &cPict::drawCustomTinyItem;
drawPict()[PIC_CUSTOM_FULL] = &cPict::drawFullSheet;
drawPict()[PIC_CUSTOM_BOOM] = &cPict::drawCustomBoom;
drawPict()[PIC_CUSTOM_MISSILE] = &cPict::drawCustomMissile;
drawPict()[PIC_CUSTOM_DLOG_LG] = &cPict::drawCustomDlogLg;
drawPict()[PIC_CUSTOM_TER_MAP] = &cPict::drawCustomTerMap;
@@ -199,6 +200,8 @@ ePicType operator+ (ePicType lhs, ePicTypeMod rhs){
return PIC_PC;
case PIC_CUSTOM_TER_MAP:
return PIC_TER_MAP;
case PIC_CUSTOM_BOOM:
return PIC_BOOM;
default:
return lhs;
}
@@ -264,6 +267,8 @@ ePicType operator+ (ePicType lhs, ePicTypeMod rhs){
return PIC_CUSTOM_TINY_ITEM;
case PIC_FULL:
return PIC_CUSTOM_FULL;
case PIC_BOOM:
return PIC_CUSTOM_BOOM;
case PIC_MISSILE:
return PIC_CUSTOM_MISSILE;
case PIC_DLOG_LG:
@@ -369,6 +374,8 @@ ePicType operator- (ePicType lhs, ePicTypeMod rhs){
return PIC_TINY_ITEM;
case PIC_CUSTOM_FULL:
return PIC_FULL;
case PIC_CUSTOM_BOOM:
return PIC_BOOM;
case PIC_CUSTOM_MISSILE:
return PIC_MISSILE;
case PIC_CUSTOM_DLOG_LG:
@@ -447,7 +454,7 @@ void cPict::recalcRect() {
case PIC_ITEM: case PIC_CUSTOM_ITEM: case PIC_PARTY_ITEM:
case PIC_PC: case PIC_PARTY_PC:
case PIC_FIELD:
case PIC_BOOM:
case PIC_BOOM: case PIC_CUSTOM_BOOM:
bounds.width() = 28;
bounds.height() = 36;
break;
@@ -807,6 +814,8 @@ void cPict::drawPresetField(short num, rectangle to_rect){
void cPict::drawPresetBoom(short num, rectangle to_rect){
std::shared_ptr<sf::Texture> from_gw = getSheet(SHEET_BOOM);
if(num >= 8)
num = 8 * (num - 7) + animFrame % 8;
rectangle from_rect = calc_rect(num % 8, num / 8);
// TODO: Be smarter about this - we know the first row is static booms and subsequent rows are animated booms.
to_rect.right = to_rect.left + 28;
@@ -1017,6 +1026,16 @@ void cPict::drawCustomTinyItem(short num, rectangle to_rect){
rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect, sf::BlendAlpha);
}
void cPict::drawCustomBoom(short num, rectangle to_rect){
to_rect.right = to_rect.left + 28;
to_rect.bottom = to_rect.top + 36;
rectangle from_rect;
sf::Texture* from_gw;
graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num + animFrame % 8);
fill_rect(*inWindow, to_rect, sf::Color::Black);
rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect, sf::BlendAlpha);
}
void cPict::drawCustomMissile(short num, rectangle to_rect){
num += animFrame % 8;
rectangle from_rect;

View File

@@ -119,6 +119,7 @@ private:
void drawCustomTalk(short num, rectangle to_rect);
void drawCustomItem(short num, rectangle to_rect);
void drawCustomTinyItem(short num, rectangle to_rect);
void drawCustomBoom(short num, rectangle to_rect);
void drawCustomMissile(short num, rectangle to_rect);
void drawCustomTerMap(short num, rectangle to_rect);
void drawPartyMonstSm(short num, rectangle to_rect);

View File

@@ -44,6 +44,7 @@ enum ePicType {
PIC_CUSTOM_TALK = 105, ///< 32x32 talking portrait drawn from two 16x32 halves in the custom sheets
PIC_CUSTOM_SCEN = 106, ///< 32x32 scenario portrait loading from scenname.exr/scenario.png
PIC_CUSTOM_ITEM = 107, ///< 28x36 custom item graphic from the custom sheets
PIC_CUSTOM_BOOM = 110, ///< 28x36 custom explosion graphic (8 frames)
PIC_CUSTOM_FULL = 111, ///< entire sheet graphic, drawn from scenname.exr/sheetxxx.png where xxx is the number
PIC_CUSTOM_MISSILE = 112, ///< 18x18 missile graphic drawn from the the custom sheets
PIC_CUSTOM_DLOG_LG = 113, ///< 72x72 dialog graphic from the custom sheet, taken from 8 successive slots

View File

@@ -669,18 +669,25 @@ pic_num_t choose_damage_type(short cur, cDialog* parent) {
}
static pic_num_t choose_boom_type(short cur, cDialog* parent) {
static const char*const boomNames[] = {"Fire", "Magic/Cold/Electricity", "Teleport", "Magic/Electricity"};
static const std::vector<pic_num_t> pics = {12,28,20,36};
static const char*const boomNames[] = {"Fire", "Teleport", "Magic/Cold/Electricity", "Magic/Electricity", "Custom Explosion"};
static const int preset_booms = 4;
std::vector<pic_num_t> pics;
for(int i = 0; i < preset_booms; i++) pics.push_back(i + 8);
for(int i = 0; i < scenario.custom_graphics.size(); i++) {
if(scenario.custom_graphics[i] == PIC_BOOM)
pics.push_back(1000 + i);
}
short prev = cur;
if(cur < 0 || cur >= pics.size()) cur = 0;
if(cur < 0 || (cur >= preset_booms && cur < 1000) || (cur >= 1000 && cur - 1000 < pics.size() - preset_booms))
cur = 0;
cPictChoice pic_dlg(pics, PIC_BOOM, parent);
pic_dlg->getControl("prompt").setText("Select a boom type:");
pic_dlg->getControl("help").setText(boomNames[cur]);
pic_dlg->getControl("help").setText(boomNames[std::min<short>(cur,4)]);
pic_dlg.attachSelectHandler([](cPictChoice& me, int n) {
me->getControl("help").setText(boomNames[n]);
me->getControl("help").setText(boomNames[std::min<short>(n,4)]);
});
bool made_choice = pic_dlg.show(cur);
size_t item_hit = pic_dlg.getSelected();
size_t item_hit = pic_dlg.getPicChosen();
return made_choice ? item_hit : prev;
}