315 * to prevent leaks. But first we need to refcount the SpriteGroup. |
315 * to prevent leaks. But first we need to refcount the SpriteGroup. |
316 * --pasky */ |
316 * --pasky */ |
317 _engine_custom_sprites[engine][cargo] = *group; |
317 _engine_custom_sprites[engine][cargo] = *group; |
318 } |
318 } |
319 |
319 |
320 typedef RealSpriteGroup *(*resolve_callback)(SpriteGroup *spritegroup, |
320 typedef SpriteGroup *(*resolve_callback)(SpriteGroup *spritegroup, |
321 const Vehicle *veh, void *callback); /* XXX data pointer used as function pointer */ |
321 const Vehicle *veh, uint16 callback_info, void *resolve_func); /* XXX data pointer used as function pointer */ |
322 |
322 |
323 static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup, |
323 static SpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup, |
324 const Vehicle *veh, resolve_callback callback) |
324 const Vehicle *veh, uint16 callback_info, resolve_callback resolve_func) |
325 { |
325 { |
326 //debug("spgt %d", spritegroup->type); |
326 //debug("spgt %d", spritegroup->type); |
327 switch (spritegroup->type) { |
327 switch (spritegroup->type) { |
328 case SGT_REAL: |
328 case SGT_REAL: |
329 return &spritegroup->g.real; |
329 case SGT_CALLBACK: |
|
330 return spritegroup; |
330 |
331 |
331 case SGT_DETERMINISTIC: { |
332 case SGT_DETERMINISTIC: { |
332 DeterministicSpriteGroup *dsg = &spritegroup->g.determ; |
333 DeterministicSpriteGroup *dsg = &spritegroup->g.determ; |
333 SpriteGroup *target; |
334 SpriteGroup *target; |
334 int value = -1; |
335 int value = -1; |
335 |
336 |
336 //debug("[%p] Having fun resolving variable %x", veh, dsg->variable); |
337 //debug("[%p] Having fun resolving variable %x", veh, dsg->variable); |
337 |
338 if (dsg->variable == 0x0C) { |
338 if ((dsg->variable >> 6) == 0) { |
339 /* Callback ID */ |
|
340 value = callback_info & 0xFF; |
|
341 } else if ((dsg->variable >> 6) == 0) { |
339 /* General property */ |
342 /* General property */ |
340 value = GetDeterministicSpriteValue(dsg->variable); |
343 value = GetDeterministicSpriteValue(dsg->variable); |
341 } else { |
344 } else { |
342 /* Vehicle-specific property. */ |
345 /* Vehicle-specific property. */ |
343 |
346 |
470 } |
473 } |
471 } |
474 } |
472 |
475 |
473 target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group; |
476 target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group; |
474 //debug("Resolved variable %x: %d, %p", dsg->variable, value, callback); |
477 //debug("Resolved variable %x: %d, %p", dsg->variable, value, callback); |
475 return callback(target, veh, callback); |
478 return resolve_func(target, veh, callback_info, resolve_func); |
476 } |
479 } |
477 |
480 |
478 case SGT_RANDOMIZED: { |
481 case SGT_RANDOMIZED: { |
479 RandomizedSpriteGroup *rsg = &spritegroup->g.random; |
482 RandomizedSpriteGroup *rsg = &spritegroup->g.random; |
480 |
483 |
481 if (veh == NULL) { |
484 if (veh == NULL) { |
482 /* Purchase list of something. Show the first one. */ |
485 /* Purchase list of something. Show the first one. */ |
483 assert(rsg->num_groups > 0); |
486 assert(rsg->num_groups > 0); |
484 //debug("going for %p: %d", rsg->groups[0], rsg->groups[0].type); |
487 //debug("going for %p: %d", rsg->groups[0], rsg->groups[0].type); |
485 return callback(&rsg->groups[0], NULL, callback); |
488 return resolve_func(&rsg->groups[0], NULL, callback_info, resolve_func); |
486 } |
489 } |
487 |
490 |
488 if (rsg->var_scope == VSG_SCOPE_PARENT) { |
491 if (rsg->var_scope == VSG_SCOPE_PARENT) { |
489 /* First engine in the vehicle chain */ |
492 /* First engine in the vehicle chain */ |
490 if (veh->type == VEH_Train) |
493 if (veh->type == VEH_Train) |
491 veh = GetFirstVehicleInChain(veh); |
494 veh = GetFirstVehicleInChain(veh); |
492 } |
495 } |
493 |
496 |
494 return callback(EvalRandomizedSpriteGroup(rsg, veh->random_bits), veh, callback); |
497 return resolve_func(EvalRandomizedSpriteGroup(rsg, veh->random_bits), veh, callback_info, resolve_func); |
495 } |
498 } |
496 |
499 |
497 default: |
500 default: |
498 error("I don't know how to handle such a spritegroup %d!", spritegroup->type); |
501 error("I don't know how to handle such a spritegroup %d!", spritegroup->type); |
499 return NULL; |
502 return NULL; |
541 loaded = (v->cargo_count * 100) / capacity; |
544 loaded = (v->cargo_count * 100) / capacity; |
542 in_motion = (v->cur_speed != 0); |
545 in_motion = (v->cur_speed != 0); |
543 } |
546 } |
544 |
547 |
545 group = GetVehicleSpriteGroup(engine, v); |
548 group = GetVehicleSpriteGroup(engine, v); |
546 rsg = ResolveVehicleSpriteGroup(group, v, (resolve_callback) ResolveVehicleSpriteGroup); |
549 group = ResolveVehicleSpriteGroup(group, v, 0, (resolve_callback) ResolveVehicleSpriteGroup); |
547 |
550 |
548 if (rsg->sprites_per_set == 0 && cargo != 29) { /* XXX magic number */ |
551 if (group->type == SGT_REAL && group->g.real.sprites_per_set == 0 && cargo != GC_DEFAULT) { |
549 // This group is empty but perhaps there'll be a default one. |
552 // This group is empty but perhaps there'll be a default one. |
550 rsg = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][29], v, |
553 group = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][GC_DEFAULT], v, 0, |
551 (resolve_callback) ResolveVehicleSpriteGroup); |
554 (resolve_callback) ResolveVehicleSpriteGroup); |
552 } |
555 } |
|
556 |
|
557 assert(group->type == SGT_REAL); |
|
558 rsg = &group->g.real; |
553 |
559 |
554 if (!rsg->sprites_per_set) { |
560 if (!rsg->sprites_per_set) { |
555 // This group is empty. This function users should therefore |
561 // This group is empty. This function users should therefore |
556 // look up the sprite number in _engine_original_sprites. |
562 // look up the sprite number in _engine_original_sprites. |
557 return 0; |
563 return 0; |
580 |
586 |
581 r = (in_motion ? rsg->loaded[spriteset] : rsg->loading[spriteset]) + direction; |
587 r = (in_motion ? rsg->loaded[spriteset] : rsg->loading[spriteset]) + direction; |
582 return r; |
588 return r; |
583 } |
589 } |
584 |
590 |
|
591 /** |
|
592 * Evaluates a newgrf callback |
|
593 * @param callback_info info about which callback to evaluate |
|
594 * (bit 0-7) = CallBack id of the callback to use, see CallBackId enum |
|
595 * (bit 8-15) = Other info some callbacks need to have, callback specific, see CallBackId enum, not used yet |
|
596 * @param engine Engine type of the vehicle to evaluate the callback for |
|
597 * @param vehicle The vehicle to evaluate the callback for, NULL if it doesnt exist (yet) |
|
598 * @return The value the callback returned, or CALLBACK_FAILED if it failed |
|
599 */ |
|
600 uint16 GetCallBackResult(uint16 callback_info, byte engine, const Vehicle *v) |
|
601 { |
|
602 SpriteGroup *group; |
|
603 byte cargo = GC_DEFAULT; |
|
604 |
|
605 if (v != NULL) |
|
606 cargo = _global_cargo_id[_opt.landscape][v->cargo_type]; |
|
607 |
|
608 group = &_engine_custom_sprites[engine][cargo]; |
|
609 group = ResolveVehicleSpriteGroup(group, v, callback_info, (resolve_callback) ResolveVehicleSpriteGroup); |
|
610 |
|
611 if (group->type == SGT_REAL && group->g.real.sprites_per_set == 0 && cargo != GC_DEFAULT) { |
|
612 // This group is empty but perhaps there'll be a default one. |
|
613 group = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][GC_DEFAULT], v, callback_info, |
|
614 (resolve_callback) ResolveVehicleSpriteGroup); |
|
615 } |
|
616 |
|
617 if (group->type != SGT_CALLBACK) |
|
618 return CALLBACK_FAILED; |
|
619 |
|
620 return group->g.callback.result; |
|
621 } |
|
622 |
|
623 |
585 |
624 |
586 // Global variables are evil, yes, but we would end up with horribly overblown |
625 // Global variables are evil, yes, but we would end up with horribly overblown |
587 // calling convention otherwise and this should be 100% reentrant. |
626 // calling convention otherwise and this should be 100% reentrant. |
588 static byte _vsg_random_triggers; |
627 static byte _vsg_random_triggers; |
589 static byte _vsg_bits_to_reseed; |
628 static byte _vsg_bits_to_reseed; |
590 |
629 |
591 extern int _custom_sprites_base; |
630 extern int _custom_sprites_base; |
592 |
631 |
593 static RealSpriteGroup *TriggerVehicleSpriteGroup(SpriteGroup *spritegroup, |
632 static SpriteGroup *TriggerVehicleSpriteGroup(SpriteGroup *spritegroup, |
594 Vehicle *veh, resolve_callback callback) |
633 Vehicle *veh, uint16 callback_info, resolve_callback resolve_func) |
595 { |
634 { |
596 if (spritegroup->type == SGT_RANDOMIZED) { |
635 if (spritegroup->type == SGT_RANDOMIZED) { |
597 _vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits( |
636 _vsg_bits_to_reseed |= RandomizedSpriteGroupTriggeredBits( |
598 &spritegroup->g.random, |
637 &spritegroup->g.random, |
599 _vsg_random_triggers, |
638 _vsg_random_triggers, |
600 &veh->waiting_triggers |
639 &veh->waiting_triggers |
601 ); |
640 ); |
602 } |
641 } |
603 |
642 |
604 return ResolveVehicleSpriteGroup(spritegroup, veh, callback); |
643 return ResolveVehicleSpriteGroup(spritegroup, veh, callback_info, resolve_func); |
605 } |
644 } |
606 |
645 |
607 static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_random_bits, bool first) |
646 static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_random_bits, bool first) |
608 { |
647 { |
|
648 SpriteGroup *group; |
609 RealSpriteGroup *rsg; |
649 RealSpriteGroup *rsg; |
610 byte new_random_bits; |
650 byte new_random_bits; |
611 |
651 |
612 _vsg_random_triggers = trigger; |
652 _vsg_random_triggers = trigger; |
613 _vsg_bits_to_reseed = 0; |
653 _vsg_bits_to_reseed = 0; |
614 rsg = TriggerVehicleSpriteGroup(GetVehicleSpriteGroup(veh->engine_type, veh), veh, |
654 group = TriggerVehicleSpriteGroup(GetVehicleSpriteGroup(veh->engine_type, veh), veh, 0, |
615 (resolve_callback) TriggerVehicleSpriteGroup); |
655 (resolve_callback) TriggerVehicleSpriteGroup); |
616 if (rsg->sprites_per_set == 0 && veh->cargo_type != 29) { /* XXX magic number */ |
656 |
|
657 if (group->type == SGT_REAL && group->g.real.sprites_per_set == 0 && veh->cargo_type != GC_DEFAULT) { |
617 // This group turned out to be empty but perhaps there'll be a default one. |
658 // This group turned out to be empty but perhaps there'll be a default one. |
618 rsg = TriggerVehicleSpriteGroup(&_engine_custom_sprites[veh->engine_type][29], veh, |
659 group = TriggerVehicleSpriteGroup(&_engine_custom_sprites[veh->engine_type][GC_DEFAULT], veh, 0, |
619 (resolve_callback) TriggerVehicleSpriteGroup); |
660 (resolve_callback) TriggerVehicleSpriteGroup); |
620 } |
661 } |
|
662 |
|
663 assert(group->type == SGT_REAL); |
|
664 rsg = &group->g.real; |
|
665 |
621 new_random_bits = Random(); |
666 new_random_bits = Random(); |
622 veh->random_bits &= ~_vsg_bits_to_reseed; |
667 veh->random_bits &= ~_vsg_bits_to_reseed; |
623 veh->random_bits |= (first ? new_random_bits : base_random_bits) & _vsg_bits_to_reseed; |
668 veh->random_bits |= (first ? new_random_bits : base_random_bits) & _vsg_bits_to_reseed; |
624 |
669 |
625 switch (trigger) { |
670 switch (trigger) { |