Example #1
0
func FxHomeCallTimer(object target, proplist fx, int time)
{
	if(!master)
	{
		KillBall();
		return -1;
	}	
	
	if(GetEffect("Blocked", this))
	{
		ox=GetX();
		oy=GetY();
		return;
	}
	
	DrawParticleLine("Flash", 0, 0, ox-GetX(), oy-GetY(), 1, 0, 0, 15, hometrailparticles);
	
	if(time%7 == 0)
	{
		for(var i = 0; i < 360; i+=5)
		{
			CreateParticle("Flash", Sin(i, 3), -Cos(i, 5), 0, 0, 10, hometrailparticles2, 2);
		}
	}

	fx.x = master->GetX();
	fx.y = master->GetY();
	var angle = Angle(GetX(), GetY(), fx.x, fx.y, 10);
	var txdir = Sin(angle, Speed + 12, 10);
	var tydir = -Cos(angle, Speed + 12, 10);
	SetXDir((GetXDir() + (txdir - GetXDir())/2));
	SetYDir((GetYDir() + (tydir - GetYDir())/2));
	
	CheckForEnemies(HomeCallSize);
	
	ox=GetX();
	oy=GetY();
	
	var dst = Distance(GetX(), GetY(), fx.x, fx.y);
	if(dst < 8)
	{
		AddShield(master);
		Sound("Ball::ball_shield", false, 20);
		
		var particles =
		{
			Prototype = Particles_Glimmer(),
			R = pR,
			G = pG,
			B = pB,
			Alpha = 255,
			Size = PV_Linear(10, 0),
			OnCollision = PC_Bounce(),
		};
		CreateParticle("StarSpark", 0, 0, PV_Random(-60,60), PV_Random(-60, 60), 25, particles, 5);
		
		var particle =
		{
			Alpha = PV_Linear(255, 0),
			Size = 50,
			R = pR,
			G = pG,
			B = pB,
			BlitMode = GFX_BLIT_Additive,
		};
		master->CreateParticle("StarSpark", 0, 0, 0, 0, 7, particle, 4);
		
		FollowMaster();
		return -1;
	}
}
Example #2
0
Line Rectangle::GetRight() const {
    auto p = this->_transform.GetPosition();
    auto e = this->_half_extents;
    return {{p.GetX() + e.GetX(), p.GetY() - e.GetY()}, {p.GetX() + e.GetX(), p.GetY() + e.GetY()}};
}
Example #3
0
Vector2D Rectangle::GetBottomRight() const {
    auto p = this->_transform.GetPosition();
    auto e = this->_half_extents;
    return {p.GetX() + e.GetX(), p.GetY() + e.GetY()};
}
Example #4
0
void BackgroundDrawer::DrawYAxisVals(wxDC *dc, int tick_len, int line_width) {
	double min = m_draw->GetDrawInfo()->GetMin();
	double max = m_draw->GetDrawInfo()->GetMax();
	double dif = max - min;

	if (dif <= 0) {
		wxLogInfo(_T("%s %f %f"), m_draw->GetDrawInfo()->GetName().c_str(), min, max);
		assert(false);
	}

	//procedure for calculating distance between marks stolen from SzarpDraw2
	double x = dif;
	double step;
	int i = 0;

	if (x < 1)
		for (;x < 1; x *=10, --i);
	else
		for (;(int)x / 10; x /=10, ++i);

	if (x <= 1.5)
		step = .1;
	else if (x <= 3.)
		step = .2;
	else if (x <= 7.5)
		step = .5;
	else
		step = 1.;

	double acc = 1;

	int prec = m_draw->GetDrawInfo()->GetPrec();
				

	for (int p = prec; p > 0; --p)
		acc /= 10;

	double factor  = (i > 0) ? 10 : .1;

	for (;i; i -= i / abs(i))
		step *= factor;

	if (step < acc)
		step = acc;

    	dc->SetPen(wxPen(GetTimeAxisCol(), line_width, wxSOLID));

	int w, h;
	GetSize(&w, &h);

	h -= m_bottommargin + m_topmargin;

	for (double val = max; (min - val) < acc; val -= step) {
	//for (double val = min; (val - max) < acc; val += step) {

		int y = GetY(val);

		dc->DrawLine(m_leftmargin - tick_len, y, m_leftmargin, y);

		wxString sval = m_draw->GetDrawInfo()->GetValueStr(val, _T("- -"));
		int textw, texth;
		dc->GetTextExtent(sval, &textw, &texth);
		dc->DrawText(sval, m_leftmargin - textw - 1, y + line_width / 2 + 1 );
	}

	dc->SetPen(wxNullPen);

}
Example #5
0
void Triangle::SetX(double x) {
    SetPosition(x, GetY());
}
Example #6
0
bool Game_Character::IsInPosition(int x, int y) const {
	return ((GetX() == x) && (GetY() == y));
}
Example #7
0
void nobHarborBuilding::Draw(int x, int y)
{
    // Gebäude an sich zeichnen
    DrawBaseBuilding(x, y);

    // Hafenfeuer zeichnen // TODO auch für nicht-römer machen
    if (nation == NAT_ROMANS || nation == NAT_JAPANESE || nation == NAT_BABYLONIANS)
    {
        LOADER.GetNationImage(nation, 500 + 5 * GAMECLIENT.GetGlobalAnimation(8, 2, 1, GetObjId() + GetX() + GetY()))->Draw(x + FIRE_POS[nation].x, y + FIRE_POS[nation].y, 0, 0, 0, 0, 0, 0);
    }
    else if (nation == NAT_AFRICANS || nation == NAT_VIKINGS)
    {
        LOADER.GetMapPlayerImage(740 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, GetObjId() + GetX() + GetY()))->Draw(x + FIRE_POS[nation].x, y + FIRE_POS[nation].y);
    }

    if (nation == NAT_ROMANS)
    {
        // Zusätzliches Feuer
        LOADER.GetMapPlayerImage(740 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, GetObjId() + GetX() + GetY()))->Draw(x + EXTRAFIRE_POS[nation].x, y + EXTRAFIRE_POS[nation].y);
    }

    // Läuft gerade eine Expedition?
    if(expedition.active)
    {
        // Waren für die Expedition zeichnen

        // Bretter
        for(unsigned char i = 0; i < expedition.boards; ++i)
            LOADER.GetMapImageN(2200 + GD_BOARDS)->Draw(x + BOARDS_POS[nation].x - 5, y + BOARDS_POS[nation].y - i * 4, 0, 0, 0, 0, 0, 0);
        // Steine
        for(unsigned char i = 0; i < expedition.stones; ++i)
            LOADER.GetMapImageN(2200 + GD_STONES)->Draw(x + STONES_POS[nation].x + 8, y + STONES_POS[nation].y - i * 4, 0, 0, 0, 0, 0, 0);

        // Und den Bauarbeiter, falls er schon da ist
        if(expedition.builder)
        {
            unsigned id = GAMECLIENT.GetGlobalAnimation(1000, 7, 1, GetX() + GetY());

            const int WALKING_DISTANCE = 30;

            // Wegstrecke, die er von einem Punkt vom anderen schon gelaufen ist
            int walking_distance = (id % 500) * WALKING_DISTANCE / 500;
            // Id vom laufen
            unsigned walking_id = (id / 32) % 8;

            int right_point = x - 20 + BUILDER_POS[nation].x;

            if(id < 500)
            {
                LOADER.bob_jobs_cache[nation][JOB_BUILDER][0][walking_id].draw(right_point - walking_distance, y + BUILDER_POS[nation].y, COLOR_WHITE, COLORS[gwg->GetPlayer(player).color]);
//              LOADER.GetBobN("jobs")->Draw(23,0,false,walking_id,right_point-walking_distance,
//                  y+BUILDER_POS[nation].y,COLORS[gwg->GetPlayer(player).color]);
                //DrawShadow(right_point-walking_distance,y,walking_id,0);
            }
            else
            {
                LOADER.bob_jobs_cache[nation][JOB_BUILDER][3][walking_id].draw(right_point - WALKING_DISTANCE + walking_distance, y + BUILDER_POS[nation].y, COLOR_WHITE, COLORS[gwg->GetPlayer(player).color]);
//              LOADER.GetBobN("jobs")->Draw(23,3,false,walking_id,
//                  right_point-WALKING_DISTANCE+walking_distance,y+BUILDER_POS[nation].y,
//                  COLORS[gwg->GetPlayer(player).color]);
                //DrawShadow(right_point-WALKING_DISTANCE+walking_distance,y,walking_id,0);
            }
        }

    }
}
void ribi::con3::ConnectThreeWidget::DoComputerMove() noexcept
{
  const auto move = SuggestMove();
  assert(CanDoMove(move->GetX(),move->GetY()));
  DoMove(move->GetX(),move->GetY());
}
Example #9
0
void RenderManager::RenderObject(const Shape& shape, bool filled, ALLEGRO_BITMAP* texture) {
    //shape->Render(al_get_backbuffer(_display_context));
    auto& verts = shape.GetVerticies();
    std::vector<ALLEGRO_VERTEX> allegro_verts;
	allegro_verts.reserve(verts.size());
    for(const auto& v : verts) {
        auto p = a2de::Math::ToScreenScale(v.GetPosition());
        auto uv = v.GetUV();
        auto c = v.GetColor();
        allegro_verts.push_back(
                        std::move(ALLEGRO_VERTEX{
                            static_cast<float>(p.GetX()),
                            static_cast<float>(p.GetY()),
                            static_cast<float>(p.GetZ()),
                            static_cast<float>(uv.GetX()),
                            static_cast<float>(uv.GetY()),
                            c
                        }));
    }
    switch(shape.GetShapeType()) {
        case Shape::ShapeType::Point: {
            al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_POINT_LIST);
            break;
        } case Shape::ShapeType::Line: {
            al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_LINE_LIST);
            break;
        } case Shape::ShapeType::Rectangle: {
            filled ?
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_TRIANGLE_LIST)
                :
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_LINE_LOOP);
            break;
        } case Shape::ShapeType::Circle: {
            filled ?
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_TRIANGLE_FAN)
                :
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_POINT_LIST);
            break;
        } case Shape::ShapeType::Ellipse: {
            filled ?
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_TRIANGLE_FAN)
                :
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_POINT_LIST);
            break;
        } case Shape::ShapeType::Triangle: {
            filled ?
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_TRIANGLE_LIST)
                :
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_LINE_LOOP);
            break;
        } case Shape::ShapeType::Arc: {
            al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_LINE_STRIP);
            break;
        } case Shape::ShapeType::Polygon: {
            filled ?
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_TRIANGLE_FAN)
                :
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_LINE_LOOP);
            break;
        } case Shape::ShapeType::Spline: {
            al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_LINE_STRIP);
            break;
        } case Shape::ShapeType::Sector: {
            filled ?
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_TRIANGLE_FAN)
                :
                al_draw_prim(allegro_verts.data(), nullptr, texture, 0, allegro_verts.size(), ALLEGRO_PRIM_LINE_LOOP);
            break;
        } default: {
            /* DO NOTHING: All cases handled */;
        }
    }
}
Example #10
0
/**
 *
 *
 *  @author OLiver
 */
void nobUsual::Draw(int x, int y)
{
    // Gebäude an sich zeichnen
    DrawBaseBuilding(x, y);

    // Wenn Produktion gestoppos ist, Schild außen am Gebäude zeichnen zeichnen
    if(disable_production_virtual)
        LOADER.GetMapImageN(46)->Draw(x + BUILDING_SIGN_CONSTS[nation][type].x, y + BUILDING_SIGN_CONSTS[nation][type].y, 0, 0, 0, 0, 0, 0);

    // Rauch zeichnen

    // Raucht dieses Gebäude und ist es in Betrieb? (nur arbeitende Gebäude rauchen schließlich)
    if(BUILDING_SMOKE_CONSTS[nation][type - 10].type && is_working)
    {
        // Dann Qualm zeichnen (damit Qualm nicht synchron ist, x- und y- Koordinate als Unterscheidung
        LOADER.GetMapImageN(692 + BUILDING_SMOKE_CONSTS[nation][type - 10].type * 8 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, (GetX() + GetY()) * 100))
        ->Draw(x + BUILDING_SMOKE_CONSTS[nation][type - 10].x, y + BUILDING_SMOKE_CONSTS[nation][type - 10].y, 0, 0, 0, 0, 0, 0, 0x99EEEEEE);
    }

    // TODO: zusätzliche Dinge wie Mühlenräder, Schweinchen etc bei bestimmten Gebäuden zeichnen

    // Bei Mühle, wenn sie nicht arbeitet, immer Mühlenräder (nichtdrehend) zeichnen
    if(type == BLD_MILL && !is_working)
    {
        // Flügel der Mühle
        LOADER.GetNationImageN(nation, 250 + 5 * 49)->Draw(x, y, 0, 0, 0, 0, 0, 0);
        // Schatten der Flügel
        LOADER.GetNationImageN(nation, 250 + 5 * 49 + 1)->Draw(x, y, 0, 0, 0, 0, 0, 0, COLOR_SHADOW);
    }
    // Esel in den Kammer bei Eselzucht zeichnen
    else if(type == BLD_DONKEYBREEDER)
    {
        // Für alle Völker jeweils
        // X-Position der Esel
        const int DONKEY_X[NAT_COUNT][3] = {{13, 26, 39}, {3, 16, 30}, {2, 15, 29}, {7, 18, 30}, {3, 16, 30}};
        // Y-Position
        const int DONKEY_Y[NAT_COUNT] = { -9, -17, -21, -17, -22};
        // Animations-IDS des Esels
        const unsigned char DONKEY_ANIMATION[] =
        { 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 6, 5, 4, 4, 5, 6, 5, 7, 6, 5, 4, 3, 2, 1, 0 };

        // Die drei Esel zeichnen mithilfe von Globalanimation
        // Anzahl hängt von Produktivität der Eselzucht ab:
        // 0-29 - kein Esel
        // 30-60 - 1 Esel
        // 60-90 - 2 Esel
        // 90-100 - 3 Esel
        if(productivity >= 30) LOADER.GetMapImageN(2180 + DONKEY_ANIMATION[GAMECLIENT.GetGlobalAnimation(sizeof(DONKEY_ANIMATION), 5, 2, GetX() * (player + 2))])->Draw(x + DONKEY_X[nation][0], y + DONKEY_Y[nation]);
        if(productivity >= 60) LOADER.GetMapImageN(2180 + DONKEY_ANIMATION[GAMECLIENT.GetGlobalAnimation(sizeof(DONKEY_ANIMATION), 5, 2, GetY())])->Draw(x + DONKEY_X[nation][1], y + DONKEY_Y[nation]);
        if(productivity >= 90) LOADER.GetMapImageN(2180 + DONKEY_ANIMATION[GAMECLIENT.GetGlobalAnimation(sizeof(DONKEY_ANIMATION), 5, 2, GetX() + GetY() * (nation + 1))])->Draw(x + DONKEY_X[nation][2], y + DONKEY_Y[nation]);
    }
    // Bei Katapulthaus Katapult oben auf dem Dach zeichnen, falls er nicht "arbeitet"
    else if(type == BLD_CATAPULT && !is_working)
    {
        LOADER.GetImageN("rom_bobs", 1776)->Draw(x - 7, y - 19, 0, 0, 0, 0, 0, 0, COLOR_WHITE, COLOR_WHITE);

        if(worker)
            if(worker->GetObjId() == 696956)
                NormalFont->Draw(x, y, "hallo", 0);
    }

    // Bei Schweinefarm Schweinchen auf dem Hof zeichnen
    else if(type == BLD_PIGFARM && this->HasWorker())
    {
        // Position der 5 Schweinchen für alle 4 Völker (1. ist das große Schwein)
        const int PIG_POSITIONS[NAT_COUNT][5][2] =
        {
            //  gr. S. 1.klS 2. klS usw
            { {3, -8}, {17, 3}, { -12, 4}, { -2, 10}, { -22, 11} }, // Afrikaner
            { { -16, 0}, { -37, 0}, { -32, 8}, { -16, 10}, { -22, 18} }, // Japaner
            { { -15, 0}, { -4, 9}, { -22, 10}, {2, 19}, { -15, 20} }, // Römer
            { {5, -5}, {25, -12}, { -7, 7}, { -23, 11}, { -10, 14} }, // Wikinger
            { { -16, 5}, { -37, 5}, { -32, -1}, { -16, 15}, { -27, 18} } // Babylonier
        };


        /// Großes Schwein zeichnen
        LOADER.GetMapImageN(2160)->Draw(
            x + PIG_POSITIONS[nation][0][0], y + PIG_POSITIONS[nation][0][1], 0, 0, 0, 0, 0, 0, COLOR_SHADOW);
        LOADER.GetMapImageN(2100 + GAMECLIENT.GetGlobalAnimation(12, 3, 1, GetX() + GetY() + obj_id))->Draw(
            x + PIG_POSITIONS[nation][0][0], y + PIG_POSITIONS[nation][0][1]);

        // Die 4 kleinen Schweinchen, je nach Produktivität
        for(unsigned i = 1; i < min<unsigned>(unsigned(productivity) / 20 + 1, 5); ++i)
        {
            //A random (really, dice-rolled by hand:) ) order of the four possible pig animations, with eating three times as much as the others ones
            //To get random-looking, non synchronous, sweet little pigs
            const unsigned char smallpig_animations[63] =
            {
                0, 0, 3, 2, 0, 0, 1, 3, 0, 3, 1, 3, 2, 0, 0, 1,
                0, 0, 1, 3, 2, 0, 1, 1, 0, 0, 2, 1, 0, 1, 0, 2,
                2, 0, 0, 2, 2, 0, 1, 0, 3, 1, 2, 0, 1, 2, 2, 0,
                0, 0, 3, 0, 2, 0, 3, 0, 3, 0, 1, 1, 0, 3, 0
            };
            const unsigned short animpos = GAMECLIENT.GetGlobalAnimation(63 * 12, 63 * 4 - i * 5, 1, 183 * i + GetX() * obj_id + GetY() * i);
            LOADER.GetMapImageN(2160)->Draw(
                x + PIG_POSITIONS[nation][i][0], y + PIG_POSITIONS[nation][i][1], 0, 0, 0, 0, 0, 0, COLOR_SHADOW);
            LOADER.GetMapImageN(2112 + smallpig_animations[animpos / 12] * 12 + animpos % 12)->Draw(
                x + PIG_POSITIONS[nation][i][0], y + PIG_POSITIONS[nation][i][1]);
        }

        // Ggf. Sounds abspielen (oink oink), da soll sich der Schweinezüchter drum kümmen
        dynamic_cast<nofPigbreeder*>(worker)->MakePigSounds();
    }
    // Bei nubischen Bergwerken das Feuer vor dem Bergwerk zeichnen
    else if(type >= BLD_GRANITEMINE && type <= BLD_GOLDMINE && worker && nation == NAT_AFRICANS)
        LOADER.GetMapImageN(740 + GAMECLIENT.GetGlobalAnimation(8, 5, 2, obj_id + GetX() + GetY()))->
        Draw(x + NUBIAN_MINE_FIRE[type - BLD_GRANITEMINE][0], y + NUBIAN_MINE_FIRE[type - BLD_GRANITEMINE][1]);
}
HRESULT ui::UIRadioButtonGroup::Render(graphics::D3DInteropHelper *pD3DInteropHelper,
                                       ID2D1RenderTarget *pRenderTarget) {
  for (size_t i = 0; i < GetNumberOfElements(); ++i) {
    auto element = std::dynamic_pointer_cast<UIRadioButton>(GetElement(i));
    D2D1_MATRIX_3X2_F origMatrix;
    pRenderTarget->GetTransform(&origMatrix);
    D2D1_MATRIX_3X2_F matrix = origMatrix * D2D1::Matrix3x2F::Translation(element->GetX(), element->GetY());
    pRenderTarget->SetTransform(matrix);
    HRESULT hr = element->Render(pD3DInteropHelper, pRenderTarget);
    if (FAILED(hr)) {
      LOG(SEVERITY_LEVEL_ERROR) << L"render a child element failed, index = " << i << L", hr = " << hr;
    }
    pRenderTarget->SetTransform(origMatrix);
  }
  return S_OK;
}
Example #12
0
//鳥居
int CBossMystia::Torii(){
	SetHP(2000);
	SetTime(30);
	deffence = 0;
	for( int i = 0; i < 60; ++i ) {
		x += ( 420 - GetX() ) / 60;
		y += ( GAME_CENTER_Y - GetY() ) / 60;
		Suspend(1);
	}
	deffence = 1;
	Suspend(30);
	while( 1 ) {
		for( int k = 0; k < 2; ++k){
			//攻撃
			CTamaNormal tama;
			tama.x = GetX();
			tama.y = GetY();
			tama.type = 3;
			tama.color = 1;
			tama.v = 1;

			CDanmakuSegment d( &tama);
			d.v2 = 1.5;
			d.v1 = 1.5;

			d.a1 = -20;
			d.a2 = -180+20;
			d.Set( 4+4*GetDifficult() );
			d.Fire();
			g_pMaterial->sndFire.Play(0);
			Suspend(40);

			d.a1 = -40;
			d.a2 = +60;
			d.Set( 4+4*GetDifficult() );
			d.Fire();
			d.a1 = 180-60;
			d.a2 = 180+40;
			d.Set( 4+4*GetDifficult() );
			d.Fire();
			g_pMaterial->sndFire.Play(0);
			Suspend(40);

			d.a1 = -20;
			d.a2 = -180+20;
			d.Set( 4+4*GetDifficult() );
			d.Fire();
			g_pMaterial->sndFire.Play(0);
			Suspend(120);

			//移動
			const int move_count = 30;
			int xv,yv;
			if( k ) {
				xv = 400 - GetX();
				yv = GAME_TOP + 120 - GetY();
			}
			else {
				xv = 500 - GetX();
				yv = GAME_BOTTOM - 120 - GetY();
			}
			for( int i = 0; i < move_count; i++ ) {
				x += xv / move_count;
				y += yv / move_count;
				mt.Suspend(1);
			}
			mt.Suspend(120);
		}
	}
	return 1;
}
Example #13
0
//全体動作(出現〜会話〜通常攻撃〜スペルカード〜撃破)
int CBossMystia::Thread(){
	TSunFunctionCallback<CBossMystia> fn;
	TSunFunctionCallback<CBossMystiaBase> fnb;

	//出現
	flag = 0;
	deffence = 0;
	for( int i = 0; i < 46; i++ ){
		x -= 5;
		mt3.Suspend();
	}
	mt3.Suspend(30);

	//会話
	g_pPlayer->Talk();
	pTalk = new CTalkMystia2();
	pTalk->Start();
	while( !pTalk->IsEnd() )
		mt3.Suspend();
	SAFE_DELETE(pTalk);
	g_pPlayer->Resume();
	fntBoss.CreateList("Mystia",12);

	//通常攻撃
	SetHP(500);
	SetTime(20);
	fnb.SetFunction(this,&CBossMystiaBase::NormalAtack1);
	mt.Start(&fnb,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();

	//鳥居
	yami = 0;
	SpellCard();
	fn.SetFunction(this,&CBossMystia::Torii);
	mt.Start(&fn,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();
	SpellEnd();

	//通常攻撃
	SetHP(1000);
	SetTime(30);
	fnb.SetFunction(this,&CBossMystiaBase::NormalAtack1);
	mt.Start(&fnb,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();

	//横符
	SpellCard();
	fn.SetFunction(this,&CBossMystia::Yoko);
	mt.Start(&fn,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();
	SpellEnd();

	//通常攻撃
	SetHP(1500);
	SetTime(40);
	fnb.SetFunction(this,&CBossMystiaBase::NormalAtack1);
	mt.Start(&fnb,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();

	//縦符
	SpellCard();
	fn.SetFunction(this,&CBossMystia::Tate);
	mt.Start(&fn,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();
	SpellEnd();

	//通常攻撃
	SetHP(2000);
	SetTime(40);
	fnb.SetFunction(this,&CBossMystiaBase::NormalAtack1);
	mt.Start(&fnb,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();

	//闇符
	yami = 1;
	yami_r = 120;
	SpellCard();
	fn.SetFunction(this,&CBossMystia::Yoko);
	mt.Start(&fn,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();
	SpellEnd();

	//幕間
	flag = 0;
	deffence = 0;
	mt.Stop();
	mt3.Suspend(60);

	//酉符
	yami = 1;
	yami_r = 60;
	SpellCard();
	fn.SetFunction(this,&CBossMystia::Tate);
	mt.Start(&fn,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();
	SpellEnd();

	//幕間
	flag = 0;
	deffence = 0;
	mt.Stop();
	mt3.Suspend(60);

	//半円
	yami = 0;
	SpellCard();
	fn.SetFunction(this,&CBossMystia::HalfCircle);
	mt.Start(&fn,0x8000);
	while( !IsEnd() ) mt3.Suspend();
	mt.Stop();
	SpellEnd();

	//エフェクト
	mt.Stop();
	flag = 0;
	deffence = 0;
	g_lEffect.Add( new CEffectBreak( GetX(), GetY() ));
	g_pPlayer->Talk();
	mt3.Suspend( 60 );

	//画面外へ
	x=1000;

	//会話
	pTalk = new CTalkMystia3();
	pTalk->Start();
	while( !pTalk->IsEnd() )
	mt3.Suspend();
	SAFE_DELETE(pTalk);

	return 1;
}
Example #14
0
func Initialize()
{
	SetAction("Travel");
	SetRDir(10);
	SetObjectLayer(nil);
	//AddEffect("MoveTo", this, 1, 1, this);
	
	ox=GetX();
	oy=GetY();
	
	rangedummy = CreateObject(Dummy, 0, 0, GetOwner());
	rangedummy.Visibility = VIS_Owner;
	rangedummy->SetAction("HangOnto", this);
		var props =
		{
			R = 255,
			G = 0,
			B = 0,
			Alpha = 40,
			Size = 70,
			BlitMode = GFX_BLIT_Additive,
			Rotation = PV_Step(10, 0, 1),
			Attach = ATTACH_Back | ATTACH_MoveRelative
			
		};
	rangedummy->CreateParticle("Shockwave2", 0, 0, 0, 0, 0, props, 1);
	
	moveparticle =
	{
		Alpha = 100,
		Size = AttackSize * 2,
		R = pR,
		G = pG,
		B = pB,
		Rotation = PV_Random(0,360),
		BlitMode = GFX_BLIT_Additive,
	};
	
	moveparticle2 =
	{
		Size = PV_Linear(2,0),
		BlitMode = GFX_BLIT_Additive,
		R = pR,
		G = pG,
		B = pB,
		Attach=ATTACH_Back,
	};
	
	movetrailparticles =
	{
		Size = PV_Linear(5,0),
		BlitMode = GFX_BLIT_Additive,
		R = pR,
		G = pG,
		B = pB,
		Attach=ATTACH_Back,
	};
	
	followtrailparticles =
	{
		Size = PV_Linear(5,0),
		BlitMode = GFX_BLIT_Additive,
		R = 50,
		G = 50,
		B = 50,
		Attach=ATTACH_Back,
	};
	
	hometrailparticles =
	{
		Size = PV_Linear(5,0),
		BlitMode = GFX_BLIT_Additive,
		R = 0,
		G = 255,
		B = 255,
		Attach=ATTACH_Back,
	};
	
	hometrailparticles2 =
	{
		Size = PV_Linear(2,0),
		BlitMode = GFX_BLIT_Additive,
		R = 0,
		G = 255,
		B = 255,
		Attach=ATTACH_Back,
	};
	
	
}
Example #15
0
/**
* @brief	Executes the death process.
*
* @param	pKiller	The killer.
*/
void CNpc::OnDeathProcess(Unit *pKiller)
{
	CUser * pUser = TO_USER(pKiller);

	if (TO_NPC(this) != nullptr && pUser != nullptr)
	{
		if (pUser->isPlayer())
		{
			if (!m_bMonster)
			{
				switch (m_tNpcType)
				{
				case NPC_BIFROST_MONUMENT:
					pUser->BifrostProcess(pUser);
					break;
				case NPC_PVP_MONUMENT:
					PVPMonumentProcess(pUser);
					break;
				default:
					break;
				}
			}
			else if (m_bMonster) // Seed Quest
			{
				if (m_sSid == 700 || m_sSid == 750)
				{
					if (pUser->CheckExistEvent(STARTER_SEED_QUEST, 1))
						pUser->SaveEvent(STARTER_SEED_QUEST, 2);
				} else if (g_pMain->m_MonsterRespawnListArray.GetData(m_sSid) != nullptr) {
					if (pUser->isPVPZone() || GetZoneID() == ZONE_JURAD_MOUNTAIN)
						g_pMain->SpawnEventNpc(g_pMain->m_MonsterRespawnListArray.GetData(m_sSid)->sSid, true, GetZoneID(), GetX(), GetY(), GetZ(), g_pMain->m_MonsterRespawnListArray.GetData(m_sSid)->sCount);
				} else if (m_tNpcType == NPC_CHAOS_STONE && pUser->isPVPZone()) {
					ChaosStoneProcess(pUser,5);
				}
			}
		}
	}
}
Example #16
0
void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
#ifdef BOTS
	// This block is necessary to clean up any bot objects owned by a Client
	Bot::ProcessClientZoneChange(this);
#endif

	zoning = true;
	if (app->size != sizeof(ZoneChange_Struct)) {
		LogFile->write(EQEMuLog::Debug, "Wrong size: OP_ZoneChange, size=%d, expected %d", app->size, sizeof(ZoneChange_Struct));
		return;
	}

#if EQDEBUG >= 5
	LogFile->write(EQEMuLog::Debug, "Zone request from %s", GetName());
	DumpPacket(app);
#endif
	ZoneChange_Struct* zc=(ZoneChange_Struct*)app->pBuffer;

	uint16 target_zone_id = 0;
	uint16 target_instance_id = zc->instanceID;
	ZonePoint* zone_point = nullptr;

	//figure out where they are going.
	if(zc->zoneID == 0) {
		//client dosent know where they are going...
		//try to figure it out for them.

		switch(zone_mode) {
		case EvacToSafeCoords:
		case ZoneToSafeCoords:
			//going to safe coords, but client dosent know where?
			//assume it is this zone for now.
			target_zone_id = zone->GetZoneID();
			break;
		case GMSummon:
			target_zone_id = zonesummon_id;
			break;
		case GateToBindPoint:
			target_zone_id = m_pp.binds[0].zoneId;
			break;
		case ZoneToBindPoint:
			target_zone_id = m_pp.binds[0].zoneId;
			break;
		case ZoneSolicited: //we told the client to zone somewhere, so we know where they are going.
			target_zone_id = zonesummon_id;
			break;
		case ZoneUnsolicited: //client came up with this on its own.
			zone_point = zone->GetClosestZonePointWithoutZone(GetX(), GetY(), GetZ(), this, ZONEPOINT_NOZONE_RANGE);
			if(zone_point) {
				//we found a zone point, which is a reasonable distance away
				//assume that is the one were going with.
				target_zone_id = zone_point->target_zone_id;
				target_instance_id = zone_point->target_zone_instance;
			} else {
				//unable to find a zone point... is there anything else
				//that can be a valid un-zolicited zone request?

				CheatDetected(MQZone, zc->x, zc->y, zc->z);
				Message(13, "Invalid unsolicited zone request.");
				LogFile->write(EQEMuLog::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id);
				SendZoneCancel(zc);
				return;
			}
			break;
		default:
			break;
		};
	}
	else {
		// This is to allow both 6.2 and Titanium clients to perform a proper zoning of the client when evac/succor
		// WildcardX 27 January 2008
		if(zone_mode == EvacToSafeCoords && zonesummon_id > 0)
			target_zone_id = zonesummon_id;
		else
			target_zone_id = zc->zoneID;

		//if we are zoning to a specific zone unsolicied,
		//then until otherwise determined, they must be zoning
		//on a zone line.
		if(zone_mode == ZoneUnsolicited)
		{
			if(target_zone_id == zone->GetZoneID())
			{
				SendZoneCancel(zc);
				return;
			}

			zone_point = zone->GetClosestZonePoint(GetX(), GetY(), GetZ(), target_zone_id, this, ZONEPOINT_ZONE_RANGE);
			//if we didnt get a zone point, or its to a different zone,
			//then we assume this is invalid.
			if(!zone_point || zone_point->target_zone_id != target_zone_id) {
				LogFile->write(EQEMuLog::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id);
				CheatDetected(MQGate, zc->x, zc->y, zc->z);
				SendZoneCancel(zc);
				return;
			}
		}
	}

	if(target_instance_id > 0)
	{
		//make sure we are in it and it's unexpired.
		if(!database.VerifyInstanceAlive(target_instance_id, CharacterID()))
		{
			Message(13, "Instance ID was expired or you were not in it.");
			SendZoneCancel(zc);
			return;
		}

		if(!database.VerifyZoneInstance(target_zone_id, target_instance_id))
		{
			Message(13, "Instance ID was %u does not go with zone id %u", target_instance_id, target_zone_id);
			SendZoneCancel(zc);
			return;
		}
	}

		//make sure its a valid zone.
	const char *target_zone_name = database.GetZoneName(target_zone_id);
	if(target_zone_name == nullptr) {
		//invalid zone...
		Message(13, "Invalid target zone ID.");
		LogFile->write(EQEMuLog::Error, "Zoning %s: Unable to get zone name for zone id '%d'.", GetName(), target_zone_id);
		SendZoneCancel(zc);
		return;
	}

	//load up the safe coords, restrictions, and verify the zone name
	float safe_x, safe_y, safe_z;
	int16 minstatus = 0;
	uint8 minlevel = 0;
	char flag_needed[128];
	if(!database.GetSafePoints(target_zone_name, database.GetInstanceVersion(target_instance_id), &safe_x, &safe_y, &safe_z, &minstatus, &minlevel, flag_needed)) {
		//invalid zone...
		Message(13, "Invalid target zone while getting safe points.");
		LogFile->write(EQEMuLog::Error, "Zoning %s: Unable to get safe coordinates for zone '%s'.", GetName(), target_zone_name);
		SendZoneCancel(zc);
		return;
	}

	char buf[10];
	snprintf(buf, 9, "%d", target_zone_id);
	buf[9] = '\0';
	parse->EventPlayer(EVENT_ZONE, this, buf, 0);

	//handle circumvention of zone restrictions
	//we need the value when creating the outgoing packet as well.
	uint8 ignorerestrictions = zonesummon_ignorerestrictions;
	zonesummon_ignorerestrictions = 0;

	float dest_x=0, dest_y=0, dest_z=0, dest_h;
	dest_h = GetHeading();
	switch(zone_mode) {
	case EvacToSafeCoords:
	case ZoneToSafeCoords:
		LogFile->write(EQEMuLog::Debug, "Zoning %s to safe coords (%f,%f,%f) in %s (%d)", GetName(), safe_x, safe_y, safe_z, target_zone_name, target_zone_id);
		dest_x = safe_x;
		dest_y = safe_y;
		dest_z = safe_z;
		break;
	case GMSummon:
		dest_x = zonesummon_x;
		dest_y = zonesummon_y;
		dest_z = zonesummon_z;
		ignorerestrictions = 1;
		break;
	case GateToBindPoint:
		dest_x = m_pp.binds[0].x;
		dest_y = m_pp.binds[0].y;
		dest_z = m_pp.binds[0].z;
		break;
	case ZoneToBindPoint:
		dest_x = m_pp.binds[0].x;
		dest_y = m_pp.binds[0].y;
		dest_z = m_pp.binds[0].z;
		ignorerestrictions = 1;	//can always get to our bind point? seems exploitable
		break;
	case ZoneSolicited: //we told the client to zone somewhere, so we know where they are going.
		//recycle zonesummon variables
		dest_x = zonesummon_x;
		dest_y = zonesummon_y;
		dest_z = zonesummon_z;
		break;
	case ZoneUnsolicited: //client came up with this on its own.
		//client requested a zoning... what are the cases when this could happen?

		//Handle zone point case:
		if(zone_point != nullptr) {
			//they are zoning using a valid zone point, figure out coords

			//999999 is a placeholder for 'same as where they were from'
			if(zone_point->target_x == 999999)
				dest_x = GetX();
			else
				dest_x = zone_point->target_x;
			if(zone_point->target_y == 999999)
				dest_y = GetY();
			else
				dest_y = zone_point->target_y;
			if(zone_point->target_z == 999999)
				dest_z=GetZ();
			else
				dest_z = zone_point->target_z;
			if(zone_point->target_heading == 999)
				dest_h = GetHeading();
			else
				dest_h = zone_point->target_heading;

			break;
		}

		//for now, there are no other cases...

		//could not find a valid reason for them to be zoning, stop it.
		CheatDetected(MQZoneUnknownDest, 0.0, 0.0, 0.0);
		LogFile->write(EQEMuLog::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%s'. Not near a zone point.", GetName(), target_zone_name);
		SendZoneCancel(zc);
		return;
	default:
		break;
	};

	//OK, now we should know where were going...

	//Check some rules first.
	int8 myerror = 1;		//1 is succes

	//not sure when we would use ZONE_ERROR_NOTREADY

	//enforce min status and level
	if (!ignorerestrictions && (Admin() < minstatus || GetLevel() < minlevel))
	{
		myerror = ZONE_ERROR_NOEXPERIENCE;
	}

	if(!ignorerestrictions && flag_needed[0] != '\0') {
		//the flag needed string is not empty, meaning a flag is required.
		if(Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(target_zone_id))
		{
			Message(13, "You do not have the flag to enter %s.", target_zone_name);
			myerror = ZONE_ERROR_NOEXPERIENCE;
		}
	}

	//TODO: ADVENTURE ENTRANCE CHECK

	if(myerror == 1) {
		//we have successfully zoned
		DoZoneSuccess(zc, target_zone_id, target_instance_id, dest_x, dest_y, dest_z, dest_h, ignorerestrictions);
	} else {
		LogFile->write(EQEMuLog::Error, "Zoning %s: Rules prevent this char from zoning into '%s'", GetName(), target_zone_name);
		SendZoneError(zc, myerror);
	}
}
Example #17
0
void Game_Character::BeginJump(const RPG::MoveRoute* current_route, int* current_index) {
	jump_x = GetX();
	jump_y = GetY();
	jump_plus_x = 0;
	jump_plus_y = 0;
	jumping = true;

	bool end_found = false;
	unsigned int i;
	for (i = *current_index; i < current_route->move_commands.size(); ++i) {
		const RPG::MoveCommand& move_command = current_route->move_commands[i];
		switch (move_command.command_id) {
			case RPG::MoveCommand::Code::move_up:
			case RPG::MoveCommand::Code::move_right:
			case RPG::MoveCommand::Code::move_down:
			case RPG::MoveCommand::Code::move_left:
			case RPG::MoveCommand::Code::move_upright:
			case RPG::MoveCommand::Code::move_downright:
			case RPG::MoveCommand::Code::move_downleft:
			case RPG::MoveCommand::Code::move_upleft:
				Move(move_command.command_id);
				break;
			case RPG::MoveCommand::Code::move_random:
				MoveRandom();
				break;
			case RPG::MoveCommand::Code::move_towards_hero:
				MoveTowardsPlayer();
				break;
			case RPG::MoveCommand::Code::move_away_from_hero:
				MoveAwayFromPlayer();
				break;
			case RPG::MoveCommand::Code::move_forward:
				MoveForward();
				break;
			default:
				break;
		}

		if (move_command.command_id == RPG::MoveCommand::Code::end_jump) {
			end_found = true;
			break;
		}
	}

	if (!end_found) {
		// No EndJump found. Move route ends directly
		*current_index = i;
		jumping = false;
		return;
	}

	int new_x = jump_x + jump_plus_x;
	int new_y = jump_y + jump_plus_y;

	if (Game_Map::LoopHorizontal()) {
		int map_width = Game_Map::GetWidth();
		if (new_x < 0) {
			jump_x += map_width;
			new_x += map_width;
		} else if (new_x >= map_width) {
			jump_x -= map_width;
			new_x -= map_width;
		}
	}

	if (Game_Map::LoopVertical()) {
		int map_height = Game_Map::GetHeight();
		if (new_y < 0) {
			jump_y += map_height;
			new_y += map_height;
		} else if (new_y >= map_height) {
			jump_y -= map_height;
			new_y -= map_height;
		}
	}

	if (
		// A character can always land on a tile they were already standing on
		!(jump_plus_x == 0 && jump_plus_y == 0) &&
		!IsLandable(new_x, new_y)
	) {
		// Reset to begin jump command and try again...
		move_failed = true;
		jumping = false;

		if (current_route->skippable) {
			*current_index = i;
			return;
		}

		return;
	}

	SetX(new_x);
	SetY(new_y);
	*current_index = i;

	remaining_step = SCREEN_TILE_WIDTH;
	stop_count = 0;
	max_stop_count = (GetMoveFrequency() > 7) ? 0 : pow(2.0, 9 - GetMoveFrequency());
	move_failed = false;
}
Example #18
0
int main(int argc, char *argv[])
{
	char cfg[MAX_FILE_NAME_SIZE]="config.json";
	
	float lPow,rPow;
	int state=STOP, stoppedState=RUN;
	int beaconToFollow=0;
	int ret = 0;
	rob_cfg_t rob_cfg;
	rob_state_t rob_state;
	struct beaconMeasure beacon;
	int totalBeacons = 0,curGroundSensor = -1;
	double elapsed1 = 0.0, elapsed2 = 0.0, realTotal = 0.0;
	struct timeval t1, t2, t3;
	bool firstTimeStart = 1;

	memset(&rob_state, 0, sizeof(rob_state_t));


	 /* processing arguments */
	while (argc > 2)
	{
		if (strcmp(argv[1], "-cfg") == 0)
		{
		   strncpy(cfg, argv[2], 99);
		   cfg[MAX_FILE_NAME_SIZE-1]='\0';
		}
		else
		{
				break; /* the while */
		}
		argc -= 2;
		argv += 2;
	}

	cfg_parser_parse(cfg, &rob_cfg);
	// int i;
	// for(i = 0; i < rob_cfg.rob_viewer_size; i++)
	// 	printf("Viewer: %s:%d\n", rob_cfg.rob_viewers[i].hostname, rob_cfg.rob_viewers[i].port);

	InitJoystick(rob_cfg.joys_dev);

	cfg_parser_connect_viewers(&rob_cfg);

	/* Connect Robot to simulator */
	if( InitRobot(rob_cfg.robo_name, rob_cfg.robo_pos, rob_cfg.hostname) == -1)
	{
		ret = 1;
		printf( "%s Failed to connect\n", rob_cfg.robo_name);
	}

	else
	{
		totalBeacons = GetNumberOfBeacons();

		printf( "Connected: %s, Total beacons: %d\n", rob_cfg.robo_name, totalBeacons);

		state=STOP;
		while(1)
		{
			/* Reading next values from Sensors */
			ReadSensors();

			if(GetFinished()) /* Simulator has received Finish() or Robot Removed */
			{
				printf(  "Exiting: %s\n", rob_cfg.robo_name );
				state = FINISHED;

				gettimeofday(&t3, NULL);

				elapsed2 = _get_elapsed_secs(&t2, &t3);
				realTotal = _get_elapsed_secs(&t1, &t3);

				printf("to beacon | to start | total | real total\n");
				printf("& %.2f & %.2f & %.2f & %.2f \n", elapsed1, elapsed2, elapsed1 + elapsed2, realTotal);

				break;
			}

			if(state==STOP && GetStartButton()) 
			{
				state=stoppedState;  /* Restart     */

				if( firstTimeStart )
				{
					firstTimeStart = 0;
					printf("Started counting elapsed time\n");
					
					gettimeofday(&t1, NULL);
				}
			}
			if(state!=STOP && GetStopButton())  {
				stoppedState=state;
				state=STOP; /* Interrupt */
			}

			curGroundSensor = GetGroundSensor();

			switch (state)
			{
				case RUN:    /* Go */
					
					if( GetVisitingLed() )
					{
						gettimeofday(&t2, NULL);

						elapsed1 = _get_elapsed_secs(&t1, &t2);

						printf("Elapsed from origin to beacon: %f\n", elapsed1);


						state = WAIT;
						DriveMotors(0.0,0.0);
					}
					else
					{
						if( curGroundSensor == beaconToFollow )
						{
							beaconToFollow++;
							SetVisitingLed(1);
							printf("%s visited target at %d\n", rob_cfg.robo_name, GetTime());
						}
						else {

							DetermineAction(beaconToFollow, &lPow, &rPow);
							DriveMotors(lPow, rPow);
						}
					}
				
					break;

				case RETURN:    /* Go */

					if( curGroundSensor == totalBeacons )
					{
						printf("%s found home at %d\n", rob_cfg.robo_name, GetTime());
						Finish();
					}
					else {
						DetermineAction(beaconToFollow, &lPow, &rPow);
						DriveMotors(lPow, rPow);
					}
				
					break;

				case WAIT: /* Wait for others to visit target */

					if(GetReturningLed())
					{
						SetVisitingLed(0);
						state = RETURN;

						gettimeofday(&t2, NULL);
					}

					DriveMotors(0.0,0.0);

					break;
			}

			//Say(rob_cfg.robo_name);


			rob_state.state = state;

			if( (rob_state.leftAvail = IsObstacleReady(LEFT)) )
				rob_state.left = GetObstacleSensor(LEFT);

			if( (rob_state.rightAvail = IsObstacleReady(RIGHT)) )
				rob_state.right = GetObstacleSensor(RIGHT);

			if( (rob_state.centerAvail = IsObstacleReady(CENTER)) )
				rob_state.center = GetObstacleSensor(CENTER);


			if(IsGPSReady())
			{
				rob_state.x = GetX();
				rob_state.y = GetY();
			}

			// if( IsGPSDirReady() )
			// 	rob_state.dir = GetDir();

			if( IsCompassReady() )
				rob_state.dir = GetCompassSensor();


			if( ( rob_state.beaconVis = IsBeaconReady(beaconToFollow) ) )
			{
				beacon = GetBeaconSensor(beaconToFollow);

				if( ( rob_state.beaconVis = beacon.beaconVisible ) )
					rob_state.beaconDir = beacon.beaconDir;
			}

			send_all_viewer_state_message(&rob_cfg, &rob_state);


			RequestCompassSensor();

			//Request Sensors for next cycle
			if(GetTime() % 2 == 0) {

				RequestObstacleSensor(CENTER);

				if(    (GetTime() % 8) == 0
					|| beaconToFollow == totalBeacons )
					RequestGroundSensor();
				else
					RequestBeaconSensor(beaconToFollow);

			}
			else {
				RequestSensors(2, "IRSensor1", "IRSensor2");
			}
		}

		send_all_viewer_state_message(&rob_cfg, &rob_state);

	}

	printf("Doing cleanup: %s\n", rob_cfg.robo_name);

	CloseAndFreeJoystick();

	cfg_parser_close(&rob_cfg);

	return ret;
}
Example #19
0
int Game_Character::GetBushDepth() const {
	if (jumping)
		return 0;

	return Game_Map::GetBushDepth(GetX(), GetY());
}
Example #20
0
/**
 * Get the magnitude of the direction vector formed by the joystick's
 * current position relative to its origin
 *
 * @return The magnitude of the direction vector
 */
float Joystick::GetMagnitude() const {
  return sqrt(pow(GetX(), 2) + pow(GetY(), 2));
}
Example #21
0
void View::GetPointPosition(wxDC* dc, int i, int *x, int *y) const {
	*x = GetX(i);

	double value = m_draw->GetValuesTable().at(i).val;
	*y = GetY(value);
}
Example #22
0
/**
 * Get the direction of the vector formed by the joystick and its origin
 * in radians
 *
 * @return The direction of the vector in radians
 */
float Joystick::GetDirectionRadians() const { return atan2(GetX(), -GetY()); }
Example #23
0
void wxTabControl::OnDraw(wxDC& dc, bool lastInRow)
{
    // Old, but in some ways better (drawing opaque tabs)
#ifndef wxUSE_NEW_METHOD
  if (!m_view)
    return;

  // Top-left of tab view area
  int viewX = m_view->GetViewRect().x;
  int viewY = m_view->GetViewRect().y;

  // Top-left of tab control
  int tabX = GetX() + viewX;
  int tabY = GetY() + viewY;
  int tabHeightInc = 0;
  if (m_isSelected)
  {
    tabHeightInc = (m_view->GetTabSelectionHeight() - m_view->GetTabHeight());
    tabY -= tabHeightInc;
  }

  dc.SetPen(*wxTRANSPARENT_PEN);

  // Draw grey background
  if (m_view->GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR)
  {
    dc.SetBrush(*m_view->GetBackgroundBrush());

    // Add 1 because the pen is transparent. Under Motif, may be different.
#ifdef __WXMOTIF__
    dc.DrawRectangle(tabX, tabY, (GetWidth()+1), (GetHeight() + tabHeightInc));
#else
    dc.DrawRectangle(tabX, tabY, (GetWidth()+1), (GetHeight() + 1 + tabHeightInc));
#endif
  }

  // Draw highlight and shadow
  dc.SetPen(*m_view->GetHighlightPen());

  // Calculate the top of the tab beneath. It's the height of the tab, MINUS
  // a bit if the tab below happens to be selected. Check.
  wxTabControl *tabBeneath = NULL;
  int subtractThis = 0;
  if (GetColPosition() > 0)
    tabBeneath = m_view->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition());
  if (tabBeneath && tabBeneath->IsSelected())
    subtractThis = (m_view->GetTabSelectionHeight() - m_view->GetTabHeight());

  // Vertical highlight: if first tab, draw to bottom of view
  if (tabX == m_view->GetViewRect().x && (m_view->GetTabStyle() & wxTAB_STYLE_DRAW_BOX))
    dc.DrawLine(tabX, tabY, tabX, (m_view->GetViewRect().y + m_view->GetViewRect().height));
  else if (tabX == m_view->GetViewRect().x)
    // Not box drawing, just to top of view.
    dc.DrawLine(tabX, tabY, tabX, (m_view->GetViewRect().y));
  else
    dc.DrawLine(tabX, tabY, tabX, (tabY + GetHeight() + tabHeightInc - subtractThis));

  dc.DrawLine(tabX, tabY, (tabX + GetWidth()), tabY);
  dc.SetPen(*m_view->GetShadowPen());

  // Test if we're outside the right-hand edge of the view area
  if (((tabX + GetWidth()) >= m_view->GetViewRect().x + m_view->GetViewRect().width) && (m_view->GetTabStyle() & wxTAB_STYLE_DRAW_BOX))
  {
    int bottomY = m_view->GetViewRect().y + m_view->GetViewRect().height + GetY() + m_view->GetTabHeight() + m_view->GetTopMargin();
    // Add a tab height since we wish to draw to the bottom of the view.
    dc.DrawLine((tabX + GetWidth()), tabY,
      (tabX + GetWidth()), bottomY);

    // Calculate the far-right of the view, since we don't wish to
    // draw inside that
    int rightOfView = m_view->GetViewRect().x + m_view->GetViewRect().width + 1;

    // Draw the horizontal bit to connect to the view rectangle
    dc.DrawLine((wxMax((tabX + GetWidth() - m_view->GetHorizontalTabOffset()), rightOfView)), (bottomY-1),
      (tabX + GetWidth()), (bottomY-1));

    // Draw black line to emphasize shadow
    dc.SetPen(*wxBLACK_PEN);
    dc.DrawLine((tabX + GetWidth() + 1), (tabY+1),
      (tabX + GetWidth() + 1), bottomY);

    // Draw the horizontal bit to connect to the view rectangle
    dc.DrawLine((wxMax((tabX + GetWidth() - m_view->GetHorizontalTabOffset()), rightOfView)), (bottomY),
      (tabX + GetWidth() + 1), (bottomY));
  }
  else
  {
    if (lastInRow)
    {
      // 25/5/97 UNLESS it's less than the max number of positions in this row

      int topY = m_view->GetViewRect().y - m_view->GetTopMargin();

      int maxPositions = ((wxTabLayer *)m_view->GetLayers().Item(0)->GetData())->GetCount();

      // Only down to the bottom of the tab, not to the top of the view
      if ( GetRowPosition() < (maxPositions - 1) )
        topY = tabY + GetHeight() + tabHeightInc;

#ifdef __WXMOTIF__
      topY -= 1;
#endif

      // Shadow
      dc.DrawLine((tabX + GetWidth()), tabY, (tabX + GetWidth()), topY);
      // Draw black line to emphasize shadow
      dc.SetPen(*wxBLACK_PEN);
      dc.DrawLine((tabX + GetWidth() + 1), (tabY+1), (tabX + GetWidth() + 1),
         topY);
    }
    else
    {
      // Calculate the top of the tab beneath. It's the height of the tab, MINUS
      // a bit if the tab below (and next col along) happens to be selected. Check.
      wxTabControl *tabBeneath = NULL;
      int subtractThis = 0;
      if (GetColPosition() > 0)
        tabBeneath = m_view->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition() + 1);
      if (tabBeneath && tabBeneath->IsSelected())
        subtractThis = (m_view->GetTabSelectionHeight() - m_view->GetTabHeight());

#ifdef __WXMOTIF__
      subtractThis += 1;
#endif

      // Draw only to next tab down.
      dc.DrawLine((tabX + GetWidth()), tabY,
         (tabX + GetWidth()), (tabY + GetHeight() + tabHeightInc - subtractThis));

      // Draw black line to emphasize shadow
      dc.SetPen(*wxBLACK_PEN);
      dc.DrawLine((tabX + GetWidth() + 1), (tabY+1), (tabX + GetWidth() + 1),
         (tabY + GetHeight() + tabHeightInc - subtractThis));
    }
  }

  // Draw centered text
  int textY = tabY + m_view->GetVerticalTabTextSpacing() + tabHeightInc;

  if (m_isSelected)
    dc.SetFont(* m_view->GetSelectedTabFont());
  else
    dc.SetFont(* GetFont());

  wxColour col(m_view->GetTextColour());
  dc.SetTextForeground(col);
  dc.SetBackgroundMode(wxTRANSPARENT);
  long textWidth, textHeight;
  dc.GetTextExtent(GetLabel(), &textWidth, &textHeight);

  int textX = (int)(tabX + (GetWidth() - textWidth)/2.0);
  if (textX < (tabX + 2))
    textX = (tabX + 2);

  dc.SetClippingRegion(tabX, tabY, GetWidth(), GetHeight());
  dc.DrawText(GetLabel(), textX, textY);
  dc.DestroyClippingRegion();

  if (m_isSelected)
  {
    dc.SetPen(*m_view->GetHighlightPen());

    // Draw white highlight from the tab's left side to the left hand edge of the view
    dc.DrawLine(m_view->GetViewRect().x, (tabY + GetHeight() + tabHeightInc),
     tabX, (tabY + GetHeight() + tabHeightInc));

    // Draw white highlight from the tab's right side to the right hand edge of the view
    dc.DrawLine((tabX + GetWidth()), (tabY + GetHeight() + tabHeightInc),
     m_view->GetViewRect().x + m_view->GetViewRect().width, (tabY + GetHeight() + tabHeightInc));
  }
#else
    // New HEL version with rounder tabs

    if (!m_view) return;

    int tabInc   = 0;
    if (m_isSelected)
    {
        tabInc = m_view->GetTabSelectionHeight() - m_view->GetTabHeight();
    }
    int tabLeft  = GetX() + m_view->GetViewRect().x;
    int tabTop   = GetY() + m_view->GetViewRect().y - tabInc;
    int tabRight = tabLeft + m_view->GetTabWidth();
    int left     = m_view->GetViewRect().x;
    int top      = tabTop + m_view->GetTabHeight() + tabInc;
    int right    = left + m_view->GetViewRect().width;
    int bottom   = top + m_view->GetViewRect().height;

    if (m_isSelected)
    {
        // TAB is selected - draw TAB and the View's full outline

        dc.SetPen(*(m_view->GetHighlightPen()));
        wxPoint pnts[10];
        int n = 0;
        pnts[n].x = left;            pnts[n++].y = bottom;
        pnts[n].x = left;             pnts[n++].y = top;
        pnts[n].x = tabLeft;         pnts[n++].y = top;
        pnts[n].x = tabLeft;            pnts[n++].y = tabTop + 2;
        pnts[n].x = tabLeft + 2;        pnts[n++].y = tabTop;
        pnts[n].x = tabRight - 1;    pnts[n++].y = tabTop;
        dc.DrawLines(n, pnts);
        if (!lastInRow)
        {
            dc.DrawLine(
                    (tabRight + 2),
                    top,
                    right,
                    top
                    );
        }

        dc.SetPen(*(m_view->GetShadowPen()));
        dc.DrawLine(
                tabRight,
                tabTop + 2,
                tabRight,
                top
                );
        dc.DrawLine(
                right,
                top,
                right,
                bottom
                );
        dc.DrawLine(
                right,
                bottom,
                left,
                bottom
                );

        dc.SetPen(*wxBLACK_PEN);
        dc.DrawPoint(
                tabRight,
                tabTop + 1
                );
        dc.DrawPoint(
                tabRight + 1,
                tabTop + 2
                );
        if (lastInRow)
        {
            dc.DrawLine(
                tabRight + 1,
                bottom,
                tabRight + 1,
                tabTop + 1
                );
        }
        else
        {
            dc.DrawLine(
                tabRight + 1,
                tabTop + 2,
                tabRight + 1,
                top
                );
            dc.DrawLine(
                right + 1,
                top,
                right + 1,
                bottom + 1
                );
        }
        dc.DrawLine(
                right + 1,
                bottom + 1,
                left + 1,
                bottom + 1
                );
    }
    else
    {
        // TAB is not selected - just draw TAB outline and RH edge
        // if the TAB is the last in the row

        int maxPositions = ((wxTabLayer*)m_view->GetLayers().Item(0)->GetData())->GetCount();
        wxTabControl* tabBelow = 0;
        wxTabControl* tabBelowRight = 0;
        if (GetColPosition() > 0)
        {
            tabBelow = m_view->FindTabControlForPosition(
                        GetColPosition() - 1,
                        GetRowPosition()
                        );
        }
        if (!lastInRow && GetColPosition() > 0)
        {
            tabBelowRight = m_view->FindTabControlForPosition(
                        GetColPosition() - 1,
                        GetRowPosition() + 1
                        );
        }

        float raisedTop = top - m_view->GetTabSelectionHeight() +
                            m_view->GetTabHeight();

        dc.SetPen(*(m_view->GetHighlightPen()));
        wxPoint pnts[10];
        int n = 0;

        pnts[n].x = tabLeft;

        if (tabBelow && tabBelow->IsSelected())
        {
            pnts[n++].y = (long)raisedTop;
        }
        else
        {
            pnts[n++].y = top;
        }
        pnts[n].x = tabLeft;            pnts[n++].y = tabTop + 2;
        pnts[n].x = tabLeft + 2;        pnts[n++].y = tabTop;
        pnts[n].x = tabRight - 1;    pnts[n++].y = tabTop;
        dc.DrawLines(n, pnts);

        dc.SetPen(*(m_view->GetShadowPen()));
        if (GetRowPosition() >= maxPositions - 1)
        {
            dc.DrawLine(
                    tabRight,
                    (tabTop + 2),
                    tabRight,
                    bottom
                    );
            dc.DrawLine(
                    tabRight,
                    bottom,
                    (tabRight - m_view->GetHorizontalTabOffset()),
                    bottom
                    );
        }
        else
        {
            if (tabBelowRight && tabBelowRight->IsSelected())
            {
                dc.DrawLine(
                        tabRight,
                        (long)raisedTop,
                        tabRight,
                        tabTop + 1
                        );
            }
            else
            {
                dc.DrawLine(
                        tabRight,
                        top - 1,
                        tabRight,
                        tabTop + 1
                        );
            }
        }

        dc.SetPen(*wxBLACK_PEN);
        dc.DrawPoint(
                tabRight,
                tabTop + 1
                );
        dc.DrawPoint(
                tabRight + 1,
                tabTop + 2
                );
        if (GetRowPosition() >= maxPositions - 1)
        {
            // draw right hand edge to bottom of view
            dc.DrawLine(
                    tabRight + 1,
                    bottom + 1,
                    tabRight + 1,
                    tabTop + 2
                    );
            dc.DrawLine(
                    tabRight + 1,
                    bottom + 1,
                    (tabRight - m_view->GetHorizontalTabOffset()),
                    bottom + 1
                    );
        }
        else
        {
            // draw right hand edge of TAB
            if (tabBelowRight && tabBelowRight->IsSelected())
            {
                dc.DrawLine(
                        tabRight + 1,
                        (long)(raisedTop - 1),
                        tabRight + 1,
                        tabTop + 2
                        );
            }
            else
            {
                dc.DrawLine(
                        tabRight + 1,
                        top - 1,
                        tabRight + 1,
                        tabTop + 2
                        );
            }
        }
    }

    // Draw centered text
    dc.SetPen(*wxBLACK_PEN);
    if (m_isSelected)
    {
        dc.SetFont(*(m_view->GetSelectedTabFont()));
    }
    else
    {
        dc.SetFont(*(GetFont()));
    }

    wxColour col(m_view->GetTextColour());
    dc.SetTextForeground(col);
    dc.SetBackgroundMode(wxTRANSPARENT);
    long textWidth, textHeight;
    dc.GetTextExtent(GetLabel(), &textWidth, &textHeight);

    float textX = (tabLeft + tabRight - textWidth) / 2;
    float textY = (tabInc + tabTop + m_view->GetVerticalTabTextSpacing());

    dc.DrawText(GetLabel(), (long)textX, (long)textY);
#endif
}
Example #24
0
wxRealPoint ExplainShape::GetStartPoint()
{
    wxRealPoint rp(GetX() + GetBitmap().GetWidth() / 2.0 + ARROWMARGIN, GetY() - (GetHeight() - GetBitmap().GetHeight()) / 2.);
    return rp;
}
Example #25
0
// Creates amount objects of type id inside the indicated rectangle(optional) in the indicated material.
// Returns the number of iterations needed, or -1 when the placement failed.
global func PlaceObjects(id id, int amount, string mat_str, int x, int y, int wdt, int hgt, bool onsf, bool nostuck)
{
	var i, j;
	var rndx, rndy, obj;
	var mat;
	var objhgt = id->GetDefCoreVal("Height", "DefCore");
	
	mat = Material(mat_str);
	// Some failsavety.
	if (mat == -1)
		if (mat_str != "GBackSolid" && mat_str != "GBackSemiSolid" && mat_str != "GBackLiquid" && mat_str != "GBackSky")
			return -1;
	
	// Optional parameters wdt and hgt.
	if (!wdt)
		wdt = LandscapeWidth() - x - GetX();
	if (!hgt)
		hgt = LandscapeHeight() - y - GetY();

	// Cycle-saving method.
	if (mat != -1)
		while (i < amount)
		{
			// If there's isn't any or not enough of the given material, break before it gets an endless loop.
			if (j++ > 20000)
				return -1;
			// Destinated rectangle.
			rndx = x + Random(wdt);
			rndy = y + Random(hgt);
			// Positioning.
			if (GetMaterial(rndx, rndy) == mat)
			{
				// On-surface option.
				if (onsf)
					while (GBackSemiSolid(rndx, rndy) && rndy >= y)
						rndy--;
				if (rndy < y)
					continue;
				// Create and verify stuckness.
				obj = CreateObjectAbove(id, rndx, rndy + objhgt / 2, NO_OWNER);
				obj->SetR(Random(360));
				if (obj->Stuck() || nostuck)
					i++;
				else
					obj->RemoveObject();
			}
		}

	if (mat == -1)
		while (i < amount)
		{
			// If there's isn't any or not enough of the given material, break before it gets an endless loop.
			if (j++ > 20000)
				return -1;
			// Destinated rectangle.
			rndx = x + Random(wdt);
			rndy = y + Random(hgt);
			// Positioning.
			if (eval(Format("%s(%d,%d)", mat_str, rndx, rndy)))
			{
				// On-surface Option.
				if (onsf)
					while (GBackSemiSolid(rndx, rndy) && rndy >= y)
						rndy--;
				if (rndy < y)
					continue;
				// Create and verify stuckness.
				obj = CreateObjectAbove(id, rndx, rndy + objhgt / 2, NO_OWNER);
				obj->SetR(Random(360));
				if (obj->Stuck() || nostuck)
					i++;
				else
					obj->RemoveObject();
			}
		}

	return j;
}
Example #26
0
wxRealPoint ExplainShape::GetEndPoint(int kidNo)
{
    wxRealPoint rp(GetX() - GetBitmap().GetWidth() / 2.0 - ARROWMARGIN, GetY() - (GetHeight() - GetBitmap().GetHeight()) / 2. + (kidCount > 1 ? GetBitmap().GetHeight() * 2. / 3. * kidNo / (2 * kidCount - 2) : 0 ));
    return rp;
}
Example #27
0
Vector2D Rectangle::GetTopLeft() const {
    auto p = this->_transform.GetPosition();
    auto e = this->_half_extents;
    return {p.GetX() - e.GetX(), p.GetY() - e.GetY()};
}
Example #28
0
func OnMoved()
{
	lx = GetX(); ly = GetY();
	if (!cb_obj) return RemoveObject();
	return cb_obj->Call(cb_fn, cb_par, lx, ly);
}
Example #29
0
void Client::GoFish()
{

	//TODO: generate a message if we're already fishing
	/*if (!fishing_timer.Check()) {	//this isn't the right check, may need to add something to the Client class like 'bool is_fishing'
		Message_StringID(0, ALREADY_FISHING);	//You are already fishing!
		return;
	}*/

	fishing_timer.Disable();

	//we're doing this a second time (1st in Client::Handle_OP_Fishing) to make sure that, between when we started fishing & now, we're still able to fish (in case we move, change equip, etc)
	if (!CanFish())	//if we can't fish here, we don't need to bother with the rest
		return;

	//multiple entries yeilds higher probability of dropping...
	uint32 common_fish_ids[MAX_COMMON_FISH_IDS] = {
		1038, // Tattered Cloth Sandals
		1038, // Tattered Cloth Sandals
		1038, // Tattered Cloth Sandals
		13019, // Fresh Fish
		13076, // Fish Scales
		13076, // Fish Scales
		7007, // Rusty Dagger
		7007, // Rusty Dagger
		7007 // Rusty Dagger

	};

	//success formula is not researched at all

	int fishing_skill = GetSkill(SkillFishing);	//will take into account skill bonuses on pole & bait

	//make sure we still have a fishing pole on:
	int32 bslot = m_inv.HasItemByUse(ItemTypeFishingBait, 1, invWhereWorn|invWherePersonal);
	const ItemInst* Bait = nullptr;
	if(bslot != SLOT_INVALID)
		Bait = m_inv.GetItem(bslot);

	//if the bait isnt equipped, need to add its skill bonus
	if(bslot >= IDX_INV && Bait->GetItem()->SkillModType == SkillFishing) {
		fishing_skill += Bait->GetItem()->SkillModValue;
	}

	if (fishing_skill > 100)
	{
		fishing_skill = 100+((fishing_skill-100)/2);
	}

	if (MakeRandomInt(0,175) < fishing_skill) {
		uint32 food_id = 0;

		//25% chance to fish an item.
		if (MakeRandomInt(0, 399) <= fishing_skill ) {
			uint32 npc_id = 0;
			uint8 npc_chance = 0;
			food_id = database.GetZoneFishing(m_pp.zone_id, fishing_skill, npc_id, npc_chance);

			//check for add NPC
			if(npc_chance > 0 && npc_id) {
				if(npc_chance < MakeRandomInt(0, 99)) {
					const NPCType* tmp = database.GetNPCType(npc_id);
					if(tmp != nullptr) {
						NPC* npc = new NPC(tmp, nullptr, GetX()+3, GetY(), GetZ(), GetHeading(), FlyMode3);
						npc->AddLootTable();

						npc->AddToHateList(this, 1, 0, false);	//no help yelling

						entity_list.AddNPC(npc);

						Message(MT_Emote, "You fish up a little more than you bargained for...");
					}
				}
			}
		}

		//consume bait, should we always consume bait on success?
		DeleteItemInInventory(bslot, 1, true);	//do we need client update?

		if(food_id == 0) {
			int index = MakeRandomInt(0, MAX_COMMON_FISH_IDS-1);
			food_id = common_fish_ids[index];
		}

		const Item_Struct* food_item = database.GetItem(food_id);

		Message_StringID(MT_Skills, FISHING_SUCCESS);
		ItemInst* inst = database.CreateItem(food_item, 1);
		if(inst != nullptr) {
			if(CheckLoreConflict(inst->GetItem()))
			{
				Message_StringID(0, DUP_LORE);
				safe_delete(inst);
			}
			else
			{
				PushItemOnCursor(*inst);
				SendItemPacket(SLOT_CURSOR,inst,ItemPacketSummonItem);
				if(RuleB(TaskSystem, EnableTaskSystem))
					UpdateTasksForItem(ActivityFish, food_id);

				safe_delete(inst);
				inst = m_inv.GetItem(SLOT_CURSOR);
			}
		}

		std::vector<void*> args;
		args.push_back(inst);
		parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst != nullptr ? inst->GetItem()->ID : 0, &args);
	}
	else
	{
		//chance to use bait when you dont catch anything...
		if (MakeRandomInt(0, 4) == 1) {
			DeleteItemInInventory(bslot, 1, true);	//do we need client update?
			Message_StringID(MT_Skills, FISHING_LOST_BAIT);	//You lost your bait!
		} else {
			if (MakeRandomInt(0, 15) == 1)	//give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it
				//TODO: check for & consume an alcoholic beverage from inventory when this triggers, and set it as a rule that's disabled by default
				Message_StringID(MT_Skills, FISHING_SPILL_BEER);	//You spill your beer while bringing in your line.
			else
				Message_StringID(MT_Skills, FISHING_FAILED);	//You didn't catch anything.
		}

		parse->EventPlayer(EVENT_FISH_FAILURE, this, "", 0);
	}

	//chance to break fishing pole...
	//this is potentially exploitable in that they can fish
	//and then swap out items in primary slot... too lazy to fix right now
	if (MakeRandomInt(0, 49) == 1) {
		Message_StringID(MT_Skills, FISHING_POLE_BROKE);	//Your fishing pole broke!
		DeleteItemInInventory(13,0,true);
	}

	if(CheckIncreaseSkill(SkillFishing, nullptr, 5))
	{
		if(title_manager.IsNewTradeSkillTitleAvailable(SkillFishing, GetRawSkill(SkillFishing)))
			NotifyNewTitlesAvailable();
	}
}
Example #30
0
func FxDischargeStop(object target, proplist effect, int reason, bool temporary)
{
	if(temporary)
		return;
		
	Sound("Ball::ball_discharge", false, 70);
		
	var flashparticle =
	{
		Alpha = 100,
		Size = DischargeSize * 2,
		R = pR,
		G = pG,
		B = pB,
		Rotation = PV_Random(0,360),
		BlitMode = GFX_BLIT_Additive,
	};
	CreateParticle("StarSpark", 0, 0, 0, 0, 10, flashparticle, 5);
	
	for(var o in FindObjects(Find_Distance(DischargeSize), Find_Func("CanBeHit", this)))
	{
		var angle = Angle(GetX(), GetY(), o->GetX(), o->GetY());
		o->AddBallHitEffect();
		o->Fling(Sin(angle, 8), -Cos(angle, 8));
		WeaponDamage(o, DischargeDamage);
	}
	
	for(var r = 5; r < DischargeSize; r += 5)
	{
		for(var i = 0; i < 360; i+= 1)
		{
			var props = {
				Size = PV_Linear(4, 0),
				Rotation = PV_Random(0, 360),
			    R = pR,
			    G = pG,
			    B = pB,
			    Alpha = PV_Linear(255,0),
				BlitMode = GFX_BLIT_Additive,
			};
			
			var x = Sin(i, r + RandomX(-2, 2));
			var y = -Cos(i, r + RandomX(-2, 2));
			
			CreateParticle("StarSpark", x, y, 0, 0, 25, props, 2);
		}
	}
	
	var props = {
		Size = PV_Linear(20, 200),
	    R = pR,
	    G = pG,
	    B = pB,
	    Alpha = PV_Linear(180, 0),
		BlitMode = GFX_BLIT_Additive,
	};
	CreateParticle("Shockwave2", 0, 0, 0, 0, 10, props, 1);
	Sound("Ball::ball_after_discharge", false, 30);
	
	Idle();
}