// Called every frame void AMissleProjectile::Tick( float DeltaTime ) { Super::Tick(DeltaTime); if (TargetActor != nullptr) { NotifyTarget(this); FVector WantedDir = (TargetActor->GetActorLocation() - GetActorLocation()).GetSafeNormal(); WantedDir += TargetActor->GetVelocity() * WantedDir.Size() / MissleMovement->MaxSpeed; MissleMovement->Velocity += WantedDir * MissleMovement->InitialSpeed * 100.0f * DeltaTime; MissleMovement->Velocity = MissleMovement->Velocity.GetSafeNormal() * MissleMovement->MaxSpeed; FVector Dis = GetActorLocation() - (TargetActor->GetActorLocation()); if (Dis.Size() < 5) { Server_Explode(TargetActor, BP_Explosion.GetDefaultObject(), Damage); } } else { NotifyTarget(nullptr); SetLifeSpan(1.0f); } }
void Slider::MessageReceived (BMessage *message) { switch (message->what) { case 'tcVC': { float tv = 0; if (tc) { tv = atof (tc->Text()); if (tv < min) tv = min; if (tv > max) tv = max; if (step > 1 && fmod (tv - min, step)) tv = int ((tv - min)/step)*step + min; if (fmt[strlen (fmt) - 2] == '0') tv = int (tv + 0.5); RemoveChild (tc); } delete tc; tc = NULL; SetValue (tv); NotifyTarget(); break; } default: // message->PrintToStream(); inherited::MessageReceived (message); } }
void Slider::KeyDown (const char *bytes, int32 numBytes) { if (numBytes == 1) { switch (*bytes) { case B_ESCAPE: { if (tc) { // printf ("TextControl is open\n"); RemoveChild (tc); delete (tc); tc = NULL; } break; } case B_SPACE: case B_ENTER: { //printf ("Enter\n"); if (tc) { // printf ("TextControl is open\n"); BMessage *key = new BMessage ('tcVC'); MessageReceived (key); delete key; } else { knobpos = BPoint (float (value - min)/(max - min)*(width - knobsize), 1); BRect kbr = BRect (knobpos.x + sep, knobpos.y, knobpos.x + knobsize - 2 + sep, knobpos.y + height - 3); // kbr.PrintToStream(); tc = new BTextControl (kbr, "slider value field", "", "", new BMessage ('tcVC')); tc->SetTarget (this); tc->SetDivider (0); EnterFilter *filter = new EnterFilter (this); tc->TextView()->AddFilter (filter); char vs[64]; sprintf (vs, fmt, value); tc->SetText (vs); AddChild (tc); tc->MakeFocus (true); inherited::KeyDown (bytes, numBytes); } break; } case B_LEFT_ARROW: //printf ("Left\n"); if (value > min) { value -= step; Invalidate(); NotifyTarget(); } break; case B_RIGHT_ARROW: //printf ("Right\n"); if (value < max) { value += step; Invalidate(); NotifyTarget(); } break; case B_TAB: // printf ("Tab\n"); if (tc) { // printf ("TextControl is open\n"); BMessage *key = new BMessage ('tcVC'); MessageReceived (key); delete key; } else { // MakeFocus (false); inherited::KeyDown (bytes, numBytes); Invalidate(); break; } default: inherited::KeyDown (bytes, numBytes); } } else inherited::KeyDown (bytes, numBytes); }
void Slider::MouseDown (BPoint point) // Note: Still assumes horizontal slider ATM! { if (tc) // TextControl still visible... Block other mouse movement. return; BPoint knobpos = BPoint (float (value - min)/(max - min)*(width - knobsize), 1); knob = BRect (knobpos.x + 1, knobpos.y + 1, knobpos.x + knobsize - 2, knobpos.y + height - 2); ulong buttons; buttons = Window()->CurrentMessage()->FindInt32 ("buttons"); float px = -1; bool dragging = false; if (click != 2 && buttons & B_PRIMARY_MOUSE_BUTTON && !(modifiers() & B_CONTROL_KEY)) { BPoint bp, pbp; uint32 bt; GetMouse (&pbp, &bt, true); bigtime_t start = system_time(); if (knob.Contains (BPoint (pbp.x - sep, pbp.y))) { while (system_time() - start < dcspeed) { snooze (20000); GetMouse (&bp, &bt, true); if (!bt && click != 2) { click = 0; } if (bt && !click) { click = 2; } if (bp != pbp) break; } } if (click != 2) { // Now we're dragging... while (buttons) { BPoint p = BPoint (point.x - sep, point.y); float x = p.x; if (!(knob.Contains (p)) && !dragging) { if (x > knob.left) { value += step * (x - knob.right)/10; } else { value += step * (x - knob.left)/10; } if (value < min) value = min; if (value > max) value = max; if (step > 1 && fmod (value - min, step)) // Hack hack! value = int ((value - min)/step)*step + min; // if (fmt[strlen (fmt) - 2] == '0') // value = int (value + 0.5); offslid->Lock(); Invalidate (BRect (sep + 1, 0, offslid->Bounds().Width() + sep, height)); offslid->Unlock(); NotifyTarget(); } else if (px != p.x && step <= 1) // Hacks galore! { dragging = true; value = (x - knobsize/2) / (width - knobsize) * (max - min) + min; //printf ("x = %f, knobsize = %f, value = %f\n", x, knobsize, value); //printf ("Value: %f ", value); if (value < min) value = min; if (value > max) value = max; if (step > 1 && fmod (value - min, step)) value = int ((value - min)/step)*step + min; if (fmt[strlen (fmt) - 2] == '0') value = int (value + 0.5); //printf ("-> %f\n", value); offslid->Lock(); Invalidate (BRect (sep + 1, 0, offslid->Bounds().Width() + sep, height)); offslid->Unlock(); px = p.x; NotifyTarget(); } knobpos = BPoint (float (value - min)/(max - min)*(width - knobsize), 1); knob = BRect (knobpos.x + 1, knobpos.y + 1, knobpos.x + knobsize - 2, knobpos.y + height - 2); snooze (20000); GetMouse (&point, &buttons, true); } click = 1; } } if (click == 2 || buttons & B_SECONDARY_MOUSE_BUTTON || modifiers() & B_CONTROL_KEY) { click = 1; if (tc) { RemoveChild (tc); delete tc; } knobpos = BPoint (float (value - min)/(max - min)*(width - knobsize), 1); BRect kbr = BRect (knobpos.x + sep, knobpos.y, knobpos.x + knobsize - 2 + sep, knobpos.y + height - 3); // kbr.PrintToStream(); tc = new BTextControl (kbr, "slider value field", "", "", new BMessage ('tcVC')); tc->SetTarget (this); tc->SetDivider (0); EnterFilter *filter = new EnterFilter (this); tc->TextView()->AddFilter (filter); char vs[64]; sprintf (vs, fmt, value); tc->SetText (vs); AddChild (tc); tc->MakeFocus (true); } NotifyTarget (); }
void CombatManager::ApplyCombatEvent(psCombatGameEvent *event, int attack_result) { psCharacter *attacker_data = event->GetAttackerData(); psCharacter *target_data=event->GetTargetData(); MathVar *weaponDecay = NULL; MathVar *blockDecay = NULL; MathVar *armorDecay = NULL; MathEnvironment env; psItem *weapon = attacker_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot()); psItem *blockingWeapon = target_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot(),true); psItem *struckArmor = target_data->Inventory().GetEffectiveArmorInSlot(event->AttackLocation); // there may only be a decay if you actually hit your target by some means if(attack_result == ATTACK_DAMAGE || attack_result == ATTACK_BLOCKED) { // we are guaranteed some armor is present - real one, race one or base one CS_ASSERT(struckArmor); float ArmorVsWeapon = weapon->GetArmorVSWeaponResistance(struckArmor->GetBaseStats()); // clamp value between 0 and 1 ArmorVsWeapon = ArmorVsWeapon > 1.0F ? 1.0F : ArmorVsWeapon < 0.0F ? 0.0F : ArmorVsWeapon; env.Define("Weapon", weapon); // weapon that was used to attack env.Define("BlockingWeapon", blockingWeapon); // weapon that blocked the attack env.Define("Armor", struckArmor); // armor hit env.Define("ArmorVsWeapon", ArmorVsWeapon); // armor vs weapon effectiveness env.Define("Damage", event->FinalDamage); // actual damage dealt env.Define("Blocked", (attack_result == ATTACK_BLOCKED)); // identifies whether this attack was blocked calc_decay->Evaluate(&env); weaponDecay = env.Lookup("WeaponDecay"); blockDecay = env.Lookup("BlockingDecay"); armorDecay = env.Lookup("ArmorDecay"); } gemActor *gemAttacker = dynamic_cast<gemActor*> ((gemObject *) event->attacker); gemActor *gemTarget = dynamic_cast<gemActor*> ((gemObject *) event->target); switch (attack_result) { case ATTACK_DAMAGE: { bool isNearlyDead = false; if (target_data->GetMaxHP().Current() > 0.0 && target_data->GetHP()/target_data->GetMaxHP().Current() > 0.2) { if ((target_data->GetHP() - event->FinalDamage) / target_data->GetMaxHP().Current() <= 0.2) isNearlyDead = true; } psCombatEventMessage ev(event->AttackerCID, isNearlyDead ? psCombatEventMessage::COMBAT_DAMAGE_NEARLY_DEAD : psCombatEventMessage::COMBAT_DAMAGE, gemAttacker->GetEID(), gemTarget->GetEID(), event->AttackLocation, event->FinalDamage, weapon->GetAttackAnimID(gemAttacker->GetCharacterData()), gemTarget->FindAnimIndex("hit")); ev.Multicast(gemTarget->GetMulticastClients(),0,MAX_COMBAT_EVENT_RANGE); // Apply final damage if (target_data!=NULL) { gemTarget->DoDamage(gemAttacker,event->FinalDamage); if (gemAttacker) { gemAttacker->InvokeAttackScripts(gemTarget, weapon); } if (gemTarget) { gemTarget->InvokeDefenseScripts(gemAttacker, weapon); if(isNearlyDead) { gemTarget->InvokeNearlyDeadScripts(gemAttacker, weapon); } } } // If the target wasn't in combat, it is now... // Note that other modes shouldn't be interrupted automatically if (gemTarget->GetMode() == PSCHARACTER_MODE_PEACE || gemTarget->GetMode() == PSCHARACTER_MODE_WORK) { if (gemTarget->GetClient()) // Set reciprocal target gemTarget->GetClient()->SetTargetObject(gemAttacker,true); // The default stance is 'Fully Defensive'. Stance initialStance = GetStance(cacheManager, "FullyDefensive"); AttackSomeone(gemTarget,gemAttacker,initialStance); } if (weapon) { weapon->AddDecay(weaponDecay->GetValue()); } if (struckArmor) { struckArmor->AddDecay(armorDecay->GetValue()); } NotifyTarget(gemAttacker,gemTarget); break; } case ATTACK_DODGED: { psCombatEventMessage ev(event->AttackerCID, psCombatEventMessage::COMBAT_DODGE, gemAttacker->GetEID(), gemTarget->GetEID(), event->AttackLocation, 0, // no dmg on a dodge weapon->GetAttackAnimID(gemAttacker->GetCharacterData()), (unsigned int)-1); // no defense anims yet ev.Multicast(gemTarget->GetMulticastClients(),0,MAX_COMBAT_EVENT_RANGE); NotifyTarget(gemAttacker,gemTarget); break; } case ATTACK_BLOCKED: { psCombatEventMessage ev(event->AttackerCID, psCombatEventMessage::COMBAT_BLOCK, gemAttacker->GetEID(), gemTarget->GetEID(), event->AttackLocation, 0, // no dmg on a block weapon->GetAttackAnimID( gemAttacker->GetCharacterData() ), (unsigned int)-1); // no defense anims yet ev.Multicast(gemTarget->GetMulticastClients(),0,MAX_COMBAT_EVENT_RANGE); if (weapon) { weapon->AddDecay(weaponDecay->GetValue()); } if (blockingWeapon) { blockingWeapon->AddDecay(blockDecay->GetValue()); } NotifyTarget(gemAttacker,gemTarget); break; } case ATTACK_MISSED: { psCombatEventMessage ev(event->AttackerCID, psCombatEventMessage::COMBAT_MISS, gemAttacker->GetEID(), gemTarget->GetEID(), event->AttackLocation, 0, // no dmg on a miss weapon->GetAttackAnimID( gemAttacker->GetCharacterData() ), (unsigned int)-1); // no defense anims yet ev.Multicast(gemTarget->GetMulticastClients(),0,MAX_COMBAT_EVENT_RANGE); NotifyTarget(gemAttacker,gemTarget); break; } case ATTACK_OUTOFRANGE: { if (event->AttackerCID) { psserver->SendSystemError(event->AttackerCID,"You are too far away to attack!"); // Auto-stop attack is commented out below, when out of range to prevent npc kiting by jumping in and out of range //if (event->attacker && event->attacker.IsValid()) // StopAttack(dynamic_cast<gemActor*>((gemObject *) event->attacker)); // if you run away, you exit attack mode } break; } case ATTACK_BADANGLE: { if (event->AttackerCID) // if human player { psserver->SendSystemError(event->AttackerCID,"You must face the enemy to attack!"); // Auto-stop attack is commented out below, when out of range to prevent npc kiting by jumping in and out of range //if (event->attacker && event->attacker.IsValid()) // StopAttack(dynamic_cast<gemActor*>((gemObject *) event->attacker)); // if you run away, you exit attack mode } break; } case ATTACK_OUTOFAMMO: { psserver->SendSystemError(event->AttackerCID, "You are out of ammo!"); if (event->attacker && event->attacker.IsValid()) StopAttack(dynamic_cast<gemActor*>((gemObject *) event->attacker)); // if you run out of ammo, you exit attack mode break; } } }